8  NPI Registry

NLM

nlm <- function(terms) {

  req <- request("https://clinicaltables.nlm.nih.gov/api/npi_idv/v3/search?") |>
    req_url_query(
      terms   = terms,
      maxList = 500,
      count   = 500,
      offset  = 0L,
      .space  = "form"
    )

  resp <- req_perform(req) |> resp_simple_json()

  n <- resp[[1]]

  if (n > 7500L) {
    cli::cli_abort(c(
      "Your search returned {.strong {.val {n}}} results.",
      "x" = "The NLM API limit is {.strong {.emph 7,500}}."))
  }

  results <- resp[[4]] |>
    as.data.frame() |>
    set_names(c("name", "npi", "specialty", "address")) |>
    as_tbl()

  nreq <- offset_length(n, 500) > 1

  cli_n_results_requests(n, 500)

  if (false(nreq)) {

    return(results)

    } else {

      results2 <- req_perform_iterative(
      req,
      next_req        = iterate_with_offset(
        param_name    = "offset",
        start         = 500,
        offset        = 500,
        resp_complete = is_complete_with_limit(500))) |>
      map(
        function(x) {
          x <- resp_simple_json(x)
          x[[4]] |>
            as.data.frame() |>
            set_names(c("name", "npi", "specialty", "address"))
        }) |>
      rowbind()

    as_tbl(rowbind(results, results2))
  }
}

NPPES

convert_epoch <- \(x) {
  as.Date(
    as.POSIXct.numeric(
      as.numeric(x) / 1000, 
      origin = "1970-01-01"
      )
    )
}

nppes <- function(npi            = NULL,
                  entity         = NULL,
                  first          = NULL,
                  last           = NULL,
                  organization   = NULL,
                  name_type      = NULL,
                  taxonomy_desc  = NULL,
                  city           = NULL,
                  state          = NULL,
                  zip            = NULL,
                  country        = NULL) {

  x <- request("https://npiregistry.cms.hhs.gov/api/?version=2.1") |>
    req_url_query(
      number               = npi,
      enumeration_type     = entity,
      first_name           = first,
      last_name            = last,
      name_purpose         = name_type,
      organization_name    = organization,
      taxonomy_description = taxonomy_desc,
      city                 = city,
      state                = state,
      postal_code          = zip,
      country_code         = country,
      limit                = 1200L,
      skip                 = 0L
    ) |>
    perform_simple()
  
  list(
    count   = x$result_count,
    results = x$results |> as_tbl()
  )
}
ex <- nppes(npi = 1528060837)

get_vars(ex$results, is_character) |> 
  fcompute(
    npi    = number,
    entity = factor_(
      val_match(
        enumeration_type, 
        "NPI-1" ~ "I", 
        "NPI-2" ~ "O", 
        .default = "X")),
    date_created = convert_epoch(created_epoch),
    last_updated = convert_epoch(last_updated_epoch)
  ) |> 
  add_vars(slt(ex$results$basic, -enumeration_date, -last_updated, -status))
# A tibble: 1 × 12
  npi        entity date_created last_updated first_name last_name middle_name
* <chr>      <fct>  <date>       <date>       <chr>      <chr>     <chr>      
1 1528060837 I      2005-06-01   2007-07-09   JOHN       SARGEANT  B          
# ℹ 5 more variables: credential <chr>, sole_proprietor <chr>, sex <chr>,
#   name_prefix <chr>, name_suffix <chr>
# get_vars(ex$results, is_list)

yank(ex$results$addresses)
  country_code  country_name address_purpose address_type             address_1
1           US United States         MAILING          DOM 1939 OLD ANNAPOLIS RD
2           US United States        LOCATION          DOM   6000 EXECUTIVE BLVD
       city state postal_code telephone_number address_2   fax_number
1  WOODBINE    MD   217978201     301-854-6748      <NA>         <NA>
2 ROCKVILLE    MD   208523803     301-816-0020   STE 201 301-816-0334
yank(ex$results$taxonomies)
        code taxonomy_group               desc state license primary
1 225100000X                Physical Therapist    MD   14262    TRUE
yank(ex$results$practiceLocations)
yank(ex$results$identifiers)
  code                 desc                 issuer identifier state
1   01 Other (non-Medicare)              Aetna HMO    0129008    MD
2   01 Other (non-Medicare)               DOL/OWCP  146574500    MD
3   01 Other (non-Medicare)      United Healthcare     230033    MD
4   01 Other (non-Medicare)  MDIPA/Alliance/MLH/OC      38311    MD
5   01 Other (non-Medicare)                  Cigna    4074069    MD
6   01 Other (non-Medicare)              Aetna PPO    4296824    MD
7   01 Other (non-Medicare) MCR Railroad retiremnt  650003825    DC
8   01 Other (non-Medicare)    BC/BS Non Provider#       k366    MD
empty(yank(ex$results$endpoints))
[1] TRUE
empty(yank(ex$results$other_names))
[1] TRUE
npi_kind
 [1] 1225701881 1174270805 1235702796 1962116806 1013647569 1306500665
 [7] 1982296737 1083295638 1841967825 1891390084 1275117269 1992338701
[13] 1891355863 1548743511 1023473279 1861857013 1689182859 1982059275
kind <- purrr::map(
  npi_kind,
  function(x) {
    nppes(npi = x)$results
    }, 
  .progress = TRUE)

kind
[[1]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1627585585000 NPI-2            1707768606000      1225701881 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,10]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[2]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1646266470000 NPI-2            1716222184000      1174270805 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,12]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[3]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1626971928000 NPI-2            1707768904000      1235702796 <df [2 × 10]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,10]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[4]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1672956101000 NPI-2            1716223626000      1962116806 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,13]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[5]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1655341041000 NPI-2            1716221224000      1013647569 <df [2 × 10]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,12]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[6]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1635005507000 NPI-2            1716222487000      1306500665 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,11]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[7]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1612386220000 NPI-2            1612386220000      1982296737 <df [2 × 10]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,12]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[8]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1618524374000 NPI-2            1716221532000      1083295638 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,11]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[9]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1630001926000 NPI-2            1716222950000      1841967825 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,12]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[10]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1607040802000 NPI-2            1716223303000      1891390084 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,13]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[11]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1620327662000 NPI-2            1716222333000      1275117269 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,11]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[12]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1582213960000 NPI-2            1701120143000      1992338701 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,11]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[13]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1561054181000 NPI-2            1582304583000      1891355863 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,11]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[14]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses   
* <chr>         <chr>            <chr>              <chr>      <list>      
1 1536946216000 NPI-2            1536946216000      1548743511 <df [2 × 9]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,10]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[15]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1450192387000 NPI-2            1707767268000      1023473279 <df [2 × 11]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,13]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[16]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1450191708000 NPI-2            1707768221000      1861857013 <df [2 × 10]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,13]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[17]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1516648288000 NPI-2            1683135725000      1689182859 <df [2 × 10]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,12]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>

[[18]]
# A tibble: 1 × 11
  created_epoch enumeration_type last_updated_epoch number     addresses    
* <chr>         <chr>            <chr>              <chr>      <list>       
1 1461596970000 NPI-2            1461596970000      1982059275 <df [2 × 10]>
# ℹ 6 more variables: practiceLocations <list>, basic <df[,11]>,
#   taxonomies <list>, identifiers <list>, endpoints <list>, other_names <list>
purrr::list_rbind(kind) |> 
  mtt(npi    = number,
      entity = factor_(
      val_match(
        enumeration_type, 
        "NPI-1" ~ "I", 
        "NPI-2" ~ "O", 
        .default = "X")),
    date_created = convert_epoch(created_epoch),
    last_updated = convert_epoch(last_updated_epoch)) |> 
  slt(-number, -enumeration_type, -created_epoch, -last_updated_epoch)
# A tibble: 18 × 11
   addresses     practiceLocations basic$organization_n…¹ taxonomies identifiers
   <list>        <list>            <chr>                  <list>     <list>     
 1 <df [2 × 9]>  <list [0]>        VIOS FERTILITY INSTIT… <df>       <list [0]> 
 2 <df [2 × 9]>  <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
 3 <df [2 × 10]> <list [0]>        VIOS FERTILITY INSTIT… <df>       <list [0]> 
 4 <df [2 × 9]>  <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
 5 <df [2 × 10]> <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
 6 <df [2 × 9]>  <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
 7 <df [2 × 10]> <list [0]>        KINDBODY OF FL MEDICA… <df>       <list [0]> 
 8 <df [2 × 9]>  <df [2 × 9]>      PEACH STATE MEDICAL P… <df>       <list [0]> 
 9 <df [2 × 9]>  <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
10 <df [2 × 9]>  <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
11 <df [2 × 9]>  <list [0]>        PEACH STATE MEDICAL P… <df>       <list [0]> 
12 <df [2 × 9]>  <list [0]>        GARDEN STATE MEDICAL … <df>       <list [0]> 
13 <df [2 × 9]>  <df [3 × 10]>     FAHIMEH SASAN,D.O., P… <df>       <list [0]> 
14 <df [2 × 9]>  <list [0]>        EMPIRE MEDICAL PRACTI… <df>       <list [0]> 
15 <df [2 × 11]> <list [0]>        VIOS FERTILITY INSTIT… <df>       <list [0]> 
16 <df [2 × 10]> <list [0]>        CENTERS FOR REPRODUCT… <df>       <list [0]> 
17 <df [2 × 10]> <list [0]>        VIOS FERTILITY INSTIT… <df>       <list [0]> 
18 <df [2 × 10]> <list [0]>        VIOS FERTILITY INSTIT… <df>       <list [0]> 
# ℹ abbreviated name: ¹​basic$organization_name
# ℹ 19 more variables: basic$organizational_subpart <chr>,
#   $enumeration_date <chr>, $last_updated <chr>, $certification_date <chr>,
#   $status <chr>, $authorized_official_first_name <chr>,
#   $authorized_official_last_name <chr>,
#   $authorized_official_telephone_number <chr>,
#   $authorized_official_title_or_position <chr>, …