Purchasing Numbers in Bulk
Overview
This is a code snippet that runs two Number APIs. The first searches for available numbers, and the second purchases the available list of numbers. The console will print out questions that specify what parameters are intended by the user.
Full code example: Purchase Phone Numbers in Bulk
- Bash
- Python
- Node
#!/bin/bash
SW_SPACE_URL="example.signalwire.com"
SW_PROJ_KEY="AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"
SW_TOKEN="PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
sw_bulk_number_purchase_print () {
if [ "${SW_SPACE_URL:-}" == "example.signalwire.com" ] || \
[ "${SW_PROJ_KEY:-}" == "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE" ] || \
[ "${SW_TOKEN:-}" == "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ]; then
printf "ERROR: Please change the SW_SPACE, SW_PROJ_KEY, and SW_TOKEN variables with your actual info\n"
exit
fi
printf "\nWARNING!!! ABUSE OR MANIPULATION OF THIS SCRIPT MAY COST YOU!!!\n\n"
printf "In the future you can execute command as such:\n\n"
printf " bash sw_random.sh <local|tollfree> [1-50] [1-200] [dry|purchase]\n\n"
printf "Where [1-50] is how many you want per area code, and [1-200] is total numbers.\n\n"
printf "examples:\n\n"
printf " $0 local <--- will prompt you for more info\n"
printf " $0 tollfree <--- will prompt you for more info\n"
printf " $0 local 2 10 <--- will purchase 10 random local numbers, 2 from 5 random area codes\n"
printf " $0 tollfree 5 100 <--- will purchase 10 random tollfree numbers, 5 from 20 random area codes\n"
printf " $0 local 8 16 dry <--- dry run, dont acutally purchase 8 numbers from 2 random area codes, just see what's available\n"
printf " $0 local 8 16 purchase <--- real run, acutally purchase 8 local numbers from 2 random area codes\n\n\n"
}
sw_bulk_number_available () {
if [ ! ${1:-} ]; then printf "Please specify <local|tollfree> [1-50]\n"; exit; fi
if [ ${1:-} == local ]; then
#declare -a REGION=( ND )
declare -a REGION=(AL AK AZ AR CA CO CT DE FL GA
HI ID IL IN IA KS KY LA ME MD
MA MI MN MS MO MT NE NV NH NJ
NM NY NC ND OH OK OR PA RI SC
SD TN TX UT VA VT WA WV WI WY)
RAND=$(( RANDOM % ${#REGION[@]} ))
RANDOM_REGION=${REGION[${RAND:-1}]}
PHONE_LIST=$(curl --silent https://$SW_SPACE_URL/api/laml/2010-04-01/Accounts/$SW_PROJ_KEY/AvailablePhoneNumbers/US/Local.json \
-X GET \
-d "InRegion=$RANDOM_REGION" \
-u "$SW_PROJ_KEY:$SW_TOKEN" \
| jq --raw-output '.available_phone_numbers[]?.phone_number?' | head -n ${2:-1})
#| jq --raw-output '.available_phone_numbers[]?.phone_number?')
if [ "$PHONE_LIST" == '' ]; then
printf "curl request empty... trying again\n"
fi
elif [ $1 == tollfree ]; then
declare -a AREACODE=( 800 833 844 855 866 877 888 )
RAND=$(( RANDOM % ${#REGION[@]} ))
RANDOM_AREACODE=${AREACODE[${RAND:-4}]}
PHONE_LIST=$(curl --silent https://$SW_SPACE_URL/api/laml/2010-04-01/Accounts/$SW_PROJ_KEY/AvailablePhoneNumbers/US/TollFree.json \
-X GET \
-d "AreaCode=$RANDOM_AREACODE" \
-u "$SW_PROJ_KEY:$SW_TOKEN" \
| jq --raw-output '.available_phone_numbers[]?.phone_number?' | head -n ${2:-1})
# | jq --raw-output '.available_phone_numbers[]?.phone_number?')
if [ "$PHONE_LIST" == '' ]; then
printf "curl request empty... trying again\n"
fi
else
printf "please choose \"local\" or \"tollfree\"...\n"
fi
}
sw_bulk_number_purchase () {
sw_bulk_number_purchase_print
if [ ! ${1:-} ]; then
read -p "Will your numbers be \"local\" or \"tollfree\"? [local]: " TYPE
TYPE=${TYPE:-local}
else
TYPE=${1:-local}
fi
if [ ! ${2:-} ]; then
read -p "how many individual numbers from a single area code (1 thru 50)? [1]: " ATOTAL
ATOTAL=${ATOTAL:-1}
else
ATOTAL=${2:-1}
fi
if [ ${ATOTAL:-} -gt 50 ]; then
printf "ERROR: Please selecte between between 1 and 50 for total numbers from single area code.\n"
exit
fi
if [ ! ${3:-} ]; then
read -p "how manay total random numbers do you want to purchase (1-200)? [1]: " TOTAL
TOTAL=${TOTAL:-1}
else
TOTAL=${3:-1}
fi
if [ ! ${4:-} ]; then
read -p "Do you want to \"purchase\" or just do a \"dry\" run? [dry]: " ACTION
ACTION=${ACTION:-dry}
else
ACTION=${4:-dry}
fi
if [ $TOTAL -gt 10000 ]; then
printf "ERROR: Cannot use this script to purchase more than 10,000 numbers per project. Please contact sales.\n"
exit
fi
if [ $TOTAL -ge 200 ]; then
printf "HIGH COST WARNING: For accounts with proper permissions, you can specify up to 10,000 numbers with this script.\n"
fi
if [ $TOTAL -lt $ATOTAL ]; then
printf "ERROR: Check your math, individual numbers from area code should not be more than total numbers.\n"
exit
fi
if (( $TOTAL % $ATOTAL != 0 )); then
printf "ERROR: This script will divide your total numbers among area codes if specified. So please use symmetrical math in your head.\n"
printf "This Script does NOT accept odd remainders. Otherwise just leave [1-50] at default [1] for maximum randomization.\n"
exit
fi
if [ $ACTION != dry ]; then
printf "\n\n"
read -p "ATTENTION: You're purchasing a total of $TOTAL random number(s), for $ATOTAL $TYPE number(s) from $(( $TOTAL / $ATOTAL)) random area code. Hit [Enter] to continue, or Ctrl+c to abort..."
else
printf "\n\n"
read -p "You're doing a dry run total of $TOTAL random number(s), for $ATOTAL $TYPE number(s) from $(( $TOTAL / $ATOTAL)) random area code(s), [Enter] to continue, or Ctrl+c to abort..."
fi
OUTFILE=/tmp/sw_purchased_numbers_$SW_PROJ_KEY.txt
printf "" > $OUTFILE
t=0
p=1
k=1
while [ $t -lt $TOTAL ]; do
sw_bulk_number_available $TYPE $ATOTAL
if [ "${PHONE_LIST:-}" ]; then
RTOTAL=$(echo "$PHONE_LIST" | wc -l)
printf "found %s from %s Region. Adjusting totals accordingly.\n" "$RTOTAL" "$RANDOM_REGION"
while read -r PHONE; do
if [ $p -gt $TOTAL ]; then break; fi
if [ $ACTION != dry ]; then
curl https://$SW_SPACE_URL/api/laml/2010-04-01/Accounts/$SW_PROJ_KEY/IncomingPhoneNumbers.json \
-X POST \
--data-urlencode "PhoneNumber=$PHONE" \
-u "$SW_PROJ_KEY:$SW_TOKEN"
printf "\n"
printf "%s: puchased $PHONE from %s Region\n" "$p" "${RANDOM_REGION:-$RANDOM_AREACODE}" | tee -a $OUTFILE
else
printf "$p: $PHONE from ${RANDOM_REGION:-$RANDOM_AREACODE} is available\n" | tee -a $OUTFILE
fi
p=$[$p+1]
done < <(printf '%s\n' "$PHONE_LIST")
t=$[$t+$RTOTAL]
else
printf "no numbers available in %s Region... skipping that region\n" "${RANDOM_REGION:-}"
fi
k=$[$k+1]
if [ $k -gt "$[$TOTAL+1]" ]; then
printf "FATAL ERROR: unknown... killing script\n"
exit
fi
done
if [ -f $OUTFILE ]; then
#less $OUTFILE
printf "\n%s total numbers purchased for poject %s in txt located located here:\n%s\n" "$(cat $OUTFILE | wc -l)" "$SW_PROJ_KEY" "$OUTFILE"
else
printf "ERROR: no output file found: [%s]\n" "$OUTFILE"
fi
}
sw_bulk_number_purchase $@
exit 0
# Load the SignalWire Rest Client
from signalwire.rest import Client as signalwire_client
import os
# TODO: Update with your own credentials
account = "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE"
token = "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
space = "example.signalwire.com"
client = signalwire_client(
account,
token,
signalwire_space_url = space)
if space == "example.signalwire.com" or account == "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE" or token == "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX":
print("ERROR: Please change the SW_SPACE, SW_PROJ_KEY, and SW_TOKEN variables with your actual info and re-run the program\n")
exit()
def purchase_menu(available_phone_numbers):
for number_data in available_phone_numbers:
print(number_data.phone_number)
print('There are ' + str(len(available_phone_numbers)) + ' numbers that fit this criteria. \n')
print('How many numbers would you like to purchase? ')
amount_to_purchase = int(input())
numbers_to_purchase = available_phone_numbers[:amount_to_purchase]
os.system('cls' if os.name == 'nt' else 'clear')
if amount_to_purchase <= 0:
main_menu()
exit()
print("Numbers about to be purchased: ")
for number_data in numbers_to_purchase:
print(number_data.phone_number)
print('\nWould you like to proceed with purchasing these numbers? (Y / N): ')
purchase = input()
if purchase == "Y" or purchase == "y":
purchase_numbers(numbers_to_purchase)
else:
os.system('cls' if os.name == 'nt' else 'clear')
main_menu()
exit()
def purchase_numbers(numbers_to_purchase):
for number_data in numbers_to_purchase:
try:
client.incoming_phone_numbers.create(
phone_number = number_data.phone_number
)
print(number_data.phone_number + " purchased successfully!")
except Exception as e:
print("ERROR: " + str(e))
def main_menu():
print('Yo OG, please type in \'Local\' for Local numbers or \'TF\' for Toll Free (Local / TF): ')
number_type = input()
if number_type == "Local":
print('Please enter State to search by State, Area to search by 3 digit area code, or R for random area code? (State / Area / R): ')
state_or_area = input()
state_choice = ""
area_choice = ""
substring_choice = ""
if state_or_area == "State":
print('Please choose a State to purchase from: \n AL AK AZ AR CA CO CT DE FL GA \n HI ID IL IN IA KS KY LA ME MD \n MA MI MN MS MO MT NE NV NJ NM \n NY NC ND OH OK OR PA RI SC SD \n TN TX UT VA WA WV WI WY: ')
state_choice = input()
elif state_or_area == "Area":
print('Please enter in the 3 digit area code:')
area_choice = input()
print('Please choose any specific number sequence or a phrase you would like the numbers to have: ')
substring_choice = input()
try:
available_phone_numbers = client.available_phone_numbers("US") \
.local \
.list(
in_region = state_choice,
area_code = area_choice,
contains = substring_choice )
purchase_menu(available_phone_numbers)
except Exception as e:
print("ERROR: " + str(e))
elif number_type == "TF":
tf_area = ""
substring_choice = ""
print('Would you like to pick a specific Area Code? If not, press Enter to skip (833 844 855 866 877 888): ')
tf_area = input()
print('Please choose any specific number sequence or a phrase you would like the numbers to have: ')
substring_choice = input()
try:
available_phone_numbers = client.available_phone_numbers("US") \
.toll_free \
.list(
area_code = tf_area,
contains = substring_choice )
purchase_menu(available_phone_numbers)
except Exception as e:
print("ERROR: " + str(e))
else:
os.system('cls' if os.name == 'nt' else 'clear')
main_menu()
exit()
main_menu()
// Install SignalWire Rest Client
import { RestClient } from '@signalwire/compatibility-api'
import readlineSync from 'readline-sync'
// Input User Authentication into Client
const account = "XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
const token = "PTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
const space = "YOUR SPACE NAME.signalwire.com"
const client = RestClient(
account,
token,
{ signalwireSpaceUrl: space });
if (space == "example.signalwire.com" | project == "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE" | token == "PTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") {
console.log("ERROR: Please change the space, project, and token variables with your actual info and re-run the program\n")
exit();
}
function purchaseMenu(available_phone_numbers) {
available_phone_numbers.forEach((numberData) => {
console.log(numberData.phoneNumber);
})
console.log('There are ' + available_phone_numbers.length + ' numbers that fit this criteria. \n');
let amount_to_purchase = readlineSync.question('How many numbers would you like to purchase? ');
let numbers_to_purchase = available_phone_numbers.slice(0, amount_to_purchase);
console.clear();
if (numbers_to_purchase <= 0) {
mainMenu();
}
console.log("Numbers about to be purchased: ")
numbers_to_purchase.forEach((numberData) => {
console.log(numberData.phoneNumber);
});
let purchase = readlineSync.question('\nWould you like to proceed with purchasing these numbers? (Y / N): ');
if (purchase == "Y") {
purchaseNumbers(numbers_to_purchase);
} else {
console.clear();
mainMenu();
}
}
function purchaseNumbers(numbers_to_purchase) {
for (let numberData of numbers_to_purchase) {
try {
client.incomingPhoneNumbers.create({
phoneNumber: numberData.phoneNumber
}).then(() => {
console.log(numberData.phoneNumber + " purchased successfully!");
})
} catch (error) {
console.log('ERROR:', error);
}
}
}
async function mainMenu() {
let number_type = readlineSync.question('Yo OG, please type in \'Local\' for Local numbers or \'TF\' for Toll Free (Local / TF): ');
if (number_type == "Local") {
let state_or_area = readlineSync.question('Please enter State to search by State, Area to search by 3 digit area code, or R for random area code? (State / Area / R): ');
let payload = {};
let state_choice = "";
let area_choice = "";
let substring_choice = ""
if (state_or_area == "State") {
state_choice = readlineSync.question('Please choose a State to purchase from: \n AL AK AZ AR CA CO CT DE FL GA \n HI ID IL IN IA KS KY LA ME MD \n MA MI MN MS MO MT NE NV NJ NM \n NY NC ND OH OK OR PA RI SC SD \n TN TX UT VA WA WV WI WY: ');
payload.region = state_choice;
} else if (state_or_area == "Area") {
area_choice = readlineSync.question('Please enter in the 3 digit area code:');
payload.areaCode = area_choice;
}
substring_choice = readlineSync.question('Please choose any specific number sequence or a phrase you would like the numbers to have: ');
if (substring_choice != "") {
payload.contains = substring_choice;
}
client.availablePhoneNumbers("US")
.local
.list(payload)
.then((available_phone_numbers) => {
purchaseMenu(available_phone_numbers);
})
} else if (number_type == "TF") {
let payload = {};
let tf_area = "";
let substring_choice = "";
tf_area = readlineSync.question('Would you like to pick a specific Area Code? If not, press Enter to skip (833 844 855 866 877 888): ')
if (tf_area != "") {
payload.areaCode = tf_area;
}
substring_choice = readlineSync.question('Please choose any specific number sequence or a phrase you would like the numbers to have: ');
if (substring_choice != "") {
payload.contains = substring_choice;
}
client.availablePhoneNumbers("US")
.tollFree
.list(payload)
.then((available_phone_numbers) => {
purchaseMenu(available_phone_numbers);
})
} else {
console.clear();
mainMenu();
}
}
mainMenu();
Numbers that have been purchased in your account, will not be able to be released for 14 days.
Be sure to only purchase the numbers that are needed. You can always come back for more!
What are we going to do?
The goal is to order as many numbers that are needed, in the most simplistic way possible. These numbers can be customized to the user's preferences via parameters in our API requests.
These queries are then entered into our SignalWire Compatibility APIs to search for available local numbers and search for available Toll-Free numbers. Once the correct amount and type of numbers are found, we will then use the create an incoming phone number API to purchase and place these numbers into a Space.
With great power, comes great responsibility.
As a preemptive measure to prevent any unwanted purchases, this API will limit the user to only pulling 100 numbers at a time. This means that you will need to execute this code multiple times if you wish to purchase more than 100 at a given time.
cURL
Below is a working bash script example using the SignalWire REST API to purchase numbers in bulk. It generally takes two actions to purchase a single phone number.
- Get a list of available phone numbers function
sw_bulk_number_available () {
- Purchase a number from the list function
sw_bulk_number_available () {
Code Walkthrough
Let's explain some key parts of each function.
In the available function, for optimal randomization purposes, we get a list from a Region instead of an area code, for local numbers.
We're making a curl request to SignalWire with the InRegion
attribute, which will give back a JSON response of 50 numbers.
Then, we use a linux utility "jq" to parse the JSON response, giving us only the numbers themselves.
declare -a REGION=(AL AK AZ AR CA CO CT DE FL GA
HI ID IL IN IA KS KY LA ME MD
MA MI MN MS MO MT NE NV NJ
NM NY NC ND OH OK OR PA RI SC
SD TN TX UT VA WA WV WI WY)
RAND=$(( RANDOM % (47 - 0 + 1 ) + 0 ))
RANDOM_REGION=${REGION[${RAND:-1}]}
PHONE_LIST=$(curl --silent https://$SW_SPACE_URL/api/laml/2010-04-01/Accounts/$SW_PROJ_KEY/AvailablePhoneNumbers/US/Local.json \
-X GET \
-d "InRegion=$RANDOM_REGION" \
-u "$SW_PROJ_KEY:$SW_TOKEN" \
| jq --raw-output '.available_phone_numbers[].phone_number' | head -n ${2:-1})
We do a similar curl request for TollFree numbers.
Instead of specifying InRegion=
as above, we're specifying AreaCode=
.
declare -a AREACODE=( 833 844 855 866 877 888 )
RAND=$(( RANDOM % 6 ))
RANDOM_AREACODE=${AREACODE[${RAND:-4}]}
PHONE_LIST=$(curl --silent https://$SW_SPACE_URL/api/laml/2010-04-01/Accounts/$SW_PROJ_KEY/AvailablePhoneNumbers/US/TollFree.json \
-X GET \
-d "AreaCode=$RANDOM_AREACODE" \
-u "$SW_PROJ_KEY:$SW_TOKEN" \
| jq --raw-output '.available_phone_numbers[].phone_number' | head -n ${2:-1})
In the purchase function, because SignalWire returns a list of 50 numbers at a time, we need to refresh our list when it is exhausted, hence the sub-loop, until total numbers have been reached.
Numbers are purchased individually in the inner-loop's curl request, and the list is refreshed with a new area code in the outer-loop's callback to sw_bulk_number_available $TYPE $ATOTAL
.
while [ $t -lt $TOTAL ]; do
sw_bulk_number_available $TYPE $ATOTAL
while read -r PHONE; do
if [ $ACTION != dry ]; then
printf "$p: puchased $PHONE\n"
curl https://$SW_SPACE_URL/api/laml/2010-04-01/Accounts/$SW_PROJ_KEY/IncomingPhoneNumbers.json \
-X POST \
--data-urlencode "PhoneNumber=$PHONE" \
-u "$SW_PROJ_KEY:$SW_TOKEN"
else
printf "$p: $PHONE from ${RANDOM_REGION:-$RANDOM_AREACODE} is available\n"
fi
p=$[$p+1]
done < <(printf '%s\n' "$PHONE_LIST")
t=$[$t+$ATOTAL]
done
This script can be used to purchase any total of numbers up to the bounds of your account permissions. Please use the script with care. Alterations and abuse may cost you considerably. SignalWire will not be liable for costs incurred by misuse of this script.
By default, if you blindly blast your way through the defaults with the Enter key, the script will do a "dry" run, only listing the available numbers, and only 1 number, from 1 area code at that. This gives you the chance to tinker with the nuances of the script when raising quantities. You'll have to type "purchase" to actually make a purchase. See notes inside scripts for usage.