Overview -- This application will show how you can use SignalWire and the Python SDK to easily send bulk SMS through a simple script with minimal modifications. This script will read in a CSV of customer data and pull the phone numbers/first names in order to send out messages. When the full send is complete, this script will store the message data in a CSV. What do I need to run this code? -- You will need the [SignalWire Python SDK](/compatibility-api/sdks) as well as your authentication variables which can easily be found in the **API** tab of your SignalWire Space. View [here](/guides/navigating-your-space#api) to see more about navigating your Space and how to find authentication variables. In order to store the message data and export to a CSV, you will need the [pandas](https://pandas.pydata.org/) library. Full code example: Bulk SMS - Python
python import pandas as pd from signalwire.rest import Client as signalwire_client import csv import time # import client client = signalwire_client(ProjectID, AuthToken, signalwire_space_url = example.signalwire.com) # define results dict for storing client records from csv and messages list for storing data about send results = {} messages = [] # link placeholder if links need to be sent with the message # use results[customer] to query database by phone number if customized URLs are needed smsLink = https://developer.signalwire.com/ # read in CSV to dict where phone number is the key and [first name, last name] is the value with open(src/bulk_sms.csv, r, encoding=utf-8-sig) as file: reader = csv.DictReader(file) for row in reader: results[row[Number]] = [row[First], row[Last]] print(results) # loop through entries and grab first name for customer in results: # store name for matched phone number in variable to use in template firstName = (results[str(customer)][0]) print(fmessaging {firstName}) # set formatted number to the E164 version using ternary operator formattedNumber = + + customer if + not in customer else customer # send message message = client.messages.create( from_=+1xxxxxxxxxx, body=fHello {firstName}, you can access our developer portal at {smsLink} , to=formattedNumber) messages.append((message.sid, message.from_, message.to, message.body, message.date_sent)) # sleep for 1 second in order to rate limit at 1 messag per second - adjust based on your approved campaign throughput time.sleep(1) # Puts call log array into dataframe with headers for easier reading. df = pd.DataFrame(messages, columns=(Sid, From, To, Body, Date/Time Sent)) print(df.to_string) df.to_csv(BulkSendDetails.csv, index=False, encoding=utf-8) Step by Step Code Content - ### Customer Data CSV The first thing you will need is a CSV with customer data in the format of first name, last name, and phone number, like shown below: text First,Last,Number Eleanor,Shellstrop,+1xxxxxxxxxx Chidi,Anagonye,1xxxxxxxxxx Tahani,Al-Jamil,1xxxxxxxxxx Jason,Mendoza,1xxxxxxxxxx The correct country code must be included for the number to be routed correctly. You can find the correct code by country [here](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). ### main.py The first step for using any of our Compatibility APIs is to import the SignalWire library and authenticate the client. We will also import pandas and csv here. python import pandas as pd from signalwire.rest import Client as signalwire_client import csv import time # import client client = signalwire_client(ProjectID, AuthToken, signalwire_space_url = example.signalwire.com) In the next step, we define a dictionary results to store customer data and a messages list for storing each message record sent. We will open the CSV (make sure to correct the path in your code) and read each file into our results dictionary using the phone number as the key and the first name/last name as the value. If your messaging needs a link, you can use the smsLink variable to point to it or point to the dynamically generated URL through a query to your database. python # define results dict for storing client records from csv and messages list for storing data about send results = {} messages = [] # read in CSV to dict where phone number is the key and [first name, last name] is the value with open(src/bulk_sms.csv, r, encoding=utf-8-sig) as file: reader = csv.DictReader(file) for row in reader: results[row[Number]] = [row[First], row[Last]] print(results) # link placeholder if links need to be sent with the message # use results[customer] to query database by phone number if customized URLs are needed smsLink = https://example.com/ Our next section will loop through each of the results customers and store the first name and formatted phone number into variables. If the original number is not in E164 format (including the + in front of the country code), we will assign the E164 version to the formattedNumber variable. We will then send the message and append the message data to the messages array. If you do not need a link, change the template to not include smsLink. python # loop through entries and grab first name for customer in results: # store name for matched phone number in variable to use in template firstName = (results[str(customer)][0]) print(fmessaging {firstName}) # set formatted number to the E164 version using ternary operator formattedNumber = + + customer if + not in customer else customer # send message message = client.messages.create( from_=+1xxxxxxxxxx, body=fHello {firstName}, you can access our developer portal at {smsLink} , to=formattedNumber) messages.append((message.sid, message.from_, message.to, message.body, message.date_sent)) # sleep for 1 second in order to rate limit at 1 messag per second - adjust based on your approved campaign throughput time.sleep(1) Lastly, now that the bulk send is over, we will store the messages data in a pandas dataframe and export to CSV. python # Puts call log array into dataframe with headers for easier reading. df = pd.DataFrame(messages, columns=(Sid, From, To, Body, Date/Time Sent)) print(df.to_string) df.to_csv(BulkSendDetails.csv, index=False, encoding=utf-8) Sign Up Here If you would like to test this example out, [create a SignalWire account and Space](https://m.signalwire.com/signups/new?s=1). Please feel free to reach out to us on our [Community Slack](https://signalwire.community/) or create a Support ticket if you need guidance!