Skip to main content

POST /verify

Verify the license status of a healthcare provider across multiple government data sources in a single API call.

Endpoint

Request headers

Request body

Request parameters

Note on npi and dob: Both are optional but strongly recommended whenever available. Without them, identity resolution relies on name and state alone, which can produce false positives for common names — including false matches against the OIG exclusion list. Supplying npi and/or dob disambiguates the provider and clears same-name collisions.

Response

Success response — 200 OK

Response fields

Status values

verified describes the licence: found, active, no OIG exclusion. It does not assert that the licence is the profession you asked for — read profession_confirmed for that. A state whose board publishes no readable profession can return verified: true with profession_confirmed: false, which means “this person holds an active licence here, and we cannot tell you it is the one you named”.
not_found and source_unavailable are not the same thing, and treating them alike is the most common integration mistake. not_found is an answer from the board: it holds no matching record. source_unavailable is the absence of an answer: the board was unreachable and we will not guess. Route the first to your normal exception workflow and the second to a retry.

Distinguishing “no record” from “no answer”

Government license sites go down. When a state board is unreachable and we hold no usable cached result, VeriflowAPI returns status: "source_unavailable" with verified: false. We deliberately do not report not_found in that case, because “the board has no record of this provider” and “we could not ask the board” are opposite conclusions for a credentialing decision.
Recommended handling:
  • Retry after a short delay rather than treating the provider as unlicensed.
  • Do not cache a source_unavailable result as a verification outcome.
  • Route to manual review if it persists across retries.
  • Check the status page to see which sources are currently degraded, and note that federal signals (oig_excluded and NPPES identity) in the same response are still valid.
Before returning source_unavailable, we first serve the most recent cached result for that provider if one exists, flagged with source_live: false so you can see the data is not fresh.

Profession

Most states run a separate board per profession, but several publish one register covering every licensed occupation — Illinois and Connecticut among them. In those states a name on its own can match an entirely different occupation, so every verification is restricted to healthcare licences and, when you ask for one, to the profession you name.

Values

Physicians and advanced practice — physician, physician_assistant, nurse_practitioner, naturopathic_physician, podiatrist, chiropractor Behavioural health — psychologist, social_worker, counselor, marriage_family_therapist, behavior_analyst, art_therapist, music_therapist, psychiatric_technician Nursing — registered_nurse, practical_nurse, clinical_nurse_specialist, nurse_anesthetist, nurse_midwife, public_health_nurse, midwife, nursing_assistant, home_health_aide, medication_aide Rehabilitation and therapy — physical_therapist, physical_therapist_assistant, occupational_therapist, occupational_therapy_assistant, speech_language_pathologist, audiologist, respiratory_therapist, athletic_trainer, exercise_physiologist, massage_therapist, acupuncturist Dental — dentist, dental_hygienist, dental_assistant Pharmacy, vision and diagnostics — pharmacist, pharmacy_technician, optometrist, optician, radiographer, clinical_laboratory_personnel, genetic_counselor, perfusionist, hearing_instrument_specialist Public and community health — dietitian, emergency_medical, lactation_consultant, community_health_worker, nursing_home_administrator, sanitarian No state covers all of these — see the role matrix for which state verifies which, or read professions_covered on any response. An unrecognised value is rejected with 422, so a typo fails loudly rather than silently widening the search.

How the filter behaves

Sending profession narrows a check; it never widens one.
  • A licence in the profession you named is returned.
  • A licence confidently in a different profession is excluded — this is what stops a nurse’s active licence answering a question about a physician.
  • If the state does not verify the profession you named at all, you get profession_not_covered instead of not_found, before any board is asked. An LCSW in Massachusetts (physicians only) is the canonical case: previously not_found, which read as “holds no licence”.
  • A licence we cannot classify is still returned, ranked after any exact match, with profession: null and the state’s raw wording in license_type. An unmapped vocabulary costs precision, never coverage.

When profession comes back null

profession is null when the state does not publish a readable profession. Colorado is the clearest case: DORA’s public dataset ships only a coded prefix (RN, AP, APE) with no dictionary, so we return the raw code in license_type and leave profession empty rather than guess. Read license_type in that case. Omitting profession is safe. Non-healthcare licences are excluded either way — the filter only adds precision within healthcare. You will never see profession_not_covered without sending profession; without it we cannot know which role you meant, and a not_found is a real lookup miss. Read professions_covered on that response to tell the two apart.

Two states where absence is not proof

Colorado publishes only coded licence prefixes with no dictionary, and New York searches every profession the state licenses, which we have not fully enumerated. In both, professions_covered lists what we have confirmed, and a profession outside that list returns not_found after a real lookup rather than profession_not_covered, because we cannot be certain it is uncovered.

Identity resolution

Before verifying license status, VeriflowAPI resolves provider identity by matching the last name exactly, then the first name. First-name matching accepts:
  • Nicknames where one form is a prefix of the other (e.g. “Bob” vs “Robert”)
  • Middle initials included or omitted
  • Hyphenated last names
  • Minor typos in submitted names
It deliberately does not match genuinely different given names that merely look alike (e.g. “John” vs “Joan”, “Satish” vs “Satinder”). Those return not_found rather than a false match — a wrong-person confirmation is worse than a miss. Every successful match reports a match_confidence: Because name-only matching is inherently ambiguous for common names, supply an npi whenever available for high-confidence, exact-identity verification. When ambiguity cannot be resolved, we return not_found.

OIG exclusion matching

The OIG LEIE (List of Excluded Individuals/Entities) is matched by name and then narrowed by the identifiers you supply. Because roughly 90% of LEIE records carry no NPI, name is the primary key — so a common name can collide with an excluded stranger. VeriflowAPI uses npi and dob to resolve those collisions:
  • A matching npi confirms the exclusion — the strongest signal, an exact identity match.
  • A different npi or dob on a same-name record rules it out as a different person, so oig_excluded returns false.
  • A name-only match — no identifier supplied, or none on the LEIE record — is reported conservatively as oig_excluded: true. We would rather surface a possible match for your review than silently clear a real exclusion.
To avoid false positives on common names, supply dob (and npi where you have it) on every check. Most LEIE records carry a date of birth, so a dob clears a same-name stranger even when the record has no NPI.

Sandbox & testing

Test keys (vf_test_) run against the same data and coverage as production — an ordinary provider returns exactly what a live key would, including unsupported_state for states we don’t yet cover. This makes your sandbox integration faithful to production. To exercise every branch of your integration deterministically, use reserved test last names (case-insensitive) on a vf_test_ key. They work in any state and force a specific outcome, similar to test card numbers: To simulate unsupported_state, query any state we don’t cover (e.g. OH) with an ordinary name. These triggers apply only to test keys — on a live key they are treated as ordinary names.

Caching policy

To maximize uptime and minimize response time, VeriflowAPI caches responses according to the following TTL policy: When a response is served from cache, cached will be true and source_live will be false. The cache_expires_at field tells you exactly when fresh data will be fetched. This caching policy means VeriflowAPI maintains 99.9% uptime even when government source sites experience downtime.

Error responses

400 Bad Request

Returned when required parameters are missing or invalid.

401 Unauthorized

Returned when the API key is missing or invalid.

429 Too Many Requests

Returned when you exceed your plan’s rate limit.

503 Service Unavailable

Returned in the rare case that all data sources are unavailable and no cached data exists.

Code examples

Python

Node.js

Ruby