Skip to content

Instantly share code, notes, and snippets.

@MurphysChaos
Created December 11, 2018 17:29
Show Gist options
  • Save MurphysChaos/4217c413e45498799f14e1d1d6dc310f to your computer and use it in GitHub Desktop.
Save MurphysChaos/4217c413e45498799f14e1d1d6dc310f to your computer and use it in GitHub Desktop.
NPI check digit validator / registry query
#!/usr/bin/env bash
# npi - A tool I wrote while working for Stratice Healthcare, a former company
# developing a software solution for DME ordering. I no longer have any
# need for this tool but am keeping it around for posterity. JsonQuery (jq)
# is required for the query functionality.
# Usage:
# npi [-c <count>] [-v] [-f] [<digits>]
# Can be run with zero, nine, or ten digits. When run with zero digits,
# a random npi with a valid check digit is generated, with nine digits,
# the calculated check digit is displayed, and with ten digits, the check
# digit is validated.
#
# -c # Can be used with zero digits to generate <count> NPIs. There is no
# programmatic upper bound so, if you run with a very large number,
# this can tie up your computer for a while.
# -v Attempts to verify the NPI with the the US Department of Health &
# Human services. Required jq.
# -f A valid NPI starts with a 1 or a 2. This forces a check digit to
# be generated even if the first digit is something other than 1 or
# 2.
# Copyright (C) 2017 Joel Murphy
# All rights reserved
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
NUM_RE='^-?[0-9]+$'
NPI_RE='^[12][0-9]{8,9}$'
SUM=0
CHD=0
COUNT=1
VERIFY=0
FORCE=0
NPI=''
check_digit() {
# Compute check digit
SUM=0
for (( idx=$((${#ARG}-1)); idx>=0; idx-- )); do
DIGIT="${ARG:idx:1}"
if [[ $((${idx}%2)) -eq 0 ]]; then
DIGIT="$((${DIGIT}*2/10+${DIGIT}*2%10))"
fi
SUM="$((${SUM}+${DIGIT}))"
done
SUM="$((${SUM}+24))"
CHD="$((${SUM}*9%10))"
}
process_args() {
while [[ $# -ge 1 ]]; do
case "${1}" in
-c)
if [[ ${2} =~ $NUM_RE ]]; then
COUNT="${2}"
shift 2
else
echo "Invalid argument: count ${2}"
exit
fi
;;
-v)
VERIFY=1
shift 1
;;
-f)
FORCE=1
shift 1
;;
*)
if [[ ${1} =~ ${NUM_RE} ]]; then
COUNT=1
NPI="${1}"
else
echo "Invalid argument: ${1}"
exit
fi
shift 1
;;
esac
done
}
main() {
for I in $(seq 1 ${COUNT}); do
ARG=${NPI:-$((${RANDOM}${RANDOM}%200000000+100000000))}
if [[ ${FORCE} -eq 0 && ! ${ARG} =~ ${NPI_RE} ]]; then
echo "First digit must be 1 or 2"
exit
fi
if [[ ${#ARG} -eq 9 ]]; then
# Compute check digit
check_digit
echo "${ARG}${CHD}"
elif [[ ${#ARG} -eq 10 ]]; then
# Verify check digit
T_CHD=$((${ARG}%10))
ARG=$((${ARG}/10))
check_digit
if [[ CHD -eq T_CHD ]]; then
echo -e "NPI check digit is \033[1;32mvalid\033[0m"
if [[ VERIFY -eq 1 ]]; then
GET=$(curl https://npiregistry.cms.hhs.gov/api/?number=${NPI} 2>/dev/null)
if [[ $(echo "${GET}" | jq -r ".result_count") -ge 1 ]]; then
echo "${GET}" | jq -r ".results[0].basic"
else
echo "Cannot verify NPI"
fi
fi
else
echo -e "NPI check digit is \033[1;31minvalid\033[0m, should be ${CHD}"
fi
fi
done
}
process_args $@
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment