How to View Your Twilio Account Usage Using Rust
Time to read: 5 minutes
Recently, I’ve stepped through how to view your Twilio account usage information using Go. This time, I’m going to show you how to do it using Rust.
But why Rust? After all, it can be harder to learn than a number of other languages; at least in my experience.
Because I feel that many of Rust’s features – especially borrowing and scoped resource management functionality – make it an extremely compelling language to learn. Learning them can help you better appreciate the languages that you already know. What’s more, it’s a very safe language with speed approaching that of C.
Prerequisites
To follow along with this tutorial, you will need the following:
- Rust and Cargo, along with some prior experience with both
- Your preferred text editor or IDE. I recommend VIM or Visual Studio Code.
- A Twilio account (free or paid). If you are new to Twilio, click here to create a free account
- A mobile phone number that can receive SMS
Application overview
This won’t be a big Rust tutorial, but rather one that’s short, sweet, and mostly straight to the point. You’ll learn how to retrieve your Twilio account usage for the last month, sum up the total cost, and print that information to the terminal.
The code will make direct API calls and be more verbose than you would likely expect as, at least for the time being, there are no official Twilio Rust crates. That said, I’m thinking of creating them.
Scaffold a new Rust project
The first thing to do is to scaffold a new Rust project using Cargo and change in to the new project directory, by running the commands below.
Add the required dependencies
Next, you need to install the dependencies that the application needs. These are:
- dotenv: This crate merges variables defined in .env into the application’s environment variables provided by the operating system. Among other things, this ensures that secure credentials, such as your Twilio credentials, are kept out of code.
- reqwest: This crate provides a convenient, higher-level HTTP Client.
- serde, serde_derive, and serde_json: These crates, collectively, serialise responses from the Twilio API into a series of structs, making them easier to work with, programmatically.
To install them, add the following configuration to the [dependencies]
section of Cargo.toml.
Then, in the terminal, run the following command to download them.
Allowing for the speed of your network connection, they’ll be installed relatively quickly.
Set the required environment variables
The next thing to do is to set the two required environment variables, your Twilio Account SID and Auth Token, so that the code can make authenticated requests to Twilio’s APIs. To do that, create a new file named .env in the project’s top-level directory. In the new file, paste the following configuration.
Next, from the Twilio Console's Dashboard, copy your Account SID and Auth Token and paste them in place of the respective placeholders in .env for TWILIO_ACCOUNT_SID
, and TWILIO_AUTH_TOKEN
.
Now, it’s time to write some Rust code!
Write the Rust code
In your text editor or IDE of choice, open src/main.rs and paste the following code.
Now, let’s step through what’s going on.
The code starts off by defining three structs to model the JSON data returned from a successful response to Twilio’s API. An AccountUsage
struct holds the pagination information, along with a vector of UsageRecord
structs.
Each UsageRecord
struct contains a SubresourceUris
struct. These contain a list of related resources, which are URIs to UsageRecords
for the same category for today, yesterday, this month, and this year, etc.
The AccountUsage
struct defines two methods:
get_total_usage_cost()
: this calculates and returns the total account usage cost, by iterating over theUsageRecord
objects stored inusage_records
and summing theprice
fieldprint_usage_report()
: this iterates over theUsageRecord
objects stored inusage_records
, printing their start and end date, category, and price, comma-separated.
Next, the main()
function is defined. It uses the dotenv crate to load the variables defined earlier in .env into the application’s list of environment variables.
After that, it attempts to initialise account_sid
with your Twilio Account SID and auth_token
with your Twilio Auth Token from the environment variables TWILIO_ACCOUNT_SID
and TWILIO_AUTH_TOKEN
respectively. If either of them cannot be retrieved, an appropriate error message is printed to the terminal and the application exits.
If both variables were defined and retrieved, however, then two further variables are defined: page_size
and request_uri
.
page_size
stores the number of records to be retrieved, or the size of a “single page” of records.request_uri
is initialised to store the URI for the usage records endpoint, using captured identifiers to set the Account SID and page size. The page size limits the maximum number of records returned to 20.
As the URI ends with LastMonth.json
, any results returned will be limited to those in the last month and returned in JSON format. However, by changing .json
to either .csv
or .html
, the information returned would instead be formatted as CSV or HTML respectively.
In addition, there are several other paths available; these are:
Daily | This returns multiple usage records for each usage category, each representing usage over a daily time-interval. |
Monthly | This returns multiple usage records for each usage category, each representing usage over a monthly time-interval |
Yearly | This returns multiple usage records for each usage category, each representing usage over a yearly time-interval. |
ThisMonth | This returns a single usage record per usage category, for this month’s usage only. |
Today | This returns a single usage record per usage category, for today’s usage only. |
Yesterday | This returns a single usage record per usage category, for yesterday’s usage only. |
AllTime | This returns a single usage record for each usage category, each representing usage over the date-range specified. This is the same as the root /Usage/Records. |
After that, a new reqwest::blocking::Client
object, client
, is initialised and used to make a GET request to the URI defined in request_url
. It uses Client
’s basic_auth() function to authenticate the request, passing account_sid
as the username and auth_token
as the password.
As the second parameter (password
) to basic_auth
is an Option type, it allows for authentication both with and without a password. Because of that, the password (auth_token
) needs to be supplied as an Option
type. As requests to Twilio’s API require the password to be supplied, auth_token
is passed in as the Some
variant of Option
.
Next up, if the status code of the response was not HTTP 200 (OK), the code panics and exits, printing the error code to the terminal. Otherwise, the code next attempts to retrieve the response’s body as text.
If it can’t do that, the code exits, printing the reason why the body could not be extracted to the terminal. However, if the body was retrieved, Serde JSON parses it into an AccountUsage
struct: doing so makes the JSON body easier to work with programmatically.
Following that, the get_total_usage_cost
function is called to calculate the total cost of the retrieved usage records.
At this point, there’s not all that much left, but to print out the retrieved and calculated information to the terminal. First, a header indicating the information coming (“Twilio Account Usage”) is printed.
Then, an iterator is instantiated to iterate over the available usage records. This is then used to iterate over them, printing out each record’s start and end dates, category, and cost, comma-separated.
After that, the total number of records retrieved and the total cost are printed before the function exits.
Test the application
With the code completed, it’s time to test it, by running the command below.
All being well, you’ll see output similar to the following printed to the terminal.
That’s how to retrieve your Twilio account usage using Rust
There is a lot more that you can do, such as handling errors gracefully. But you’ve now learned the essentials of retrieving information from Twilio’s APIs with Rust.
What improvements would you make to the code? How would you have implemented the application? Please share your feedback, as I’m really just at the start of my journey with Rust and would love to learn from you as well.
Matthew Setter is a PHP Editor in the Twilio Voices team and a PHP and Go developer. He’s also the author of Mezzio Essentials and Docker Essentials. When he's not writing PHP code, he's editing great PHP articles here at Twilio. You can find him at msetter@twilio.com, and on Twitter, and GitHub.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.