This content originally appeared on Twilio Blog and was authored by Matthew Setter
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.
cargo new twilio_account_usage
cd twilio_account_usage
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.
dotenv = "0.15.0"
reqwest = {version="0.11.13", features = ["json"]}
serde = { version = "1.0.152", features = ["derive"] }
serde_derive = "1.0.152"
serde_json = "1.0.91"
Then, in the terminal, run the following command to download them.
cargo build
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.
TWILIO_ACCOUNT_SID="<TWILIO_ACCOUNT_SID>"
TWILIO_AUTH_TOKEN="<TWILIO_AUTH_TOKEN>"
Make sure you add .env to .gitignore in your normal projects, so that it’s not accidentally tracked.
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.
use dotenv::dotenv;
use reqwest::{blocking::Client, Error, StatusCode};
use serde::{Deserialize, Serialize};
use std::env;
#[derive(Serialize, Deserialize)]
struct AccountUsage {
first_page_uri: String,
last_page_uri: Option<String>,
next_page_uri: Option<String>,
previous_page_uri: Option<String>,
num_pages: Option<u8>,
page: u8,
page_size: u8,
start: u8,
end: u8,
total: Option<u8>,
uri: String,
usage_records: Vec<UsageRecord>,
}
#[derive(Serialize, Deserialize)]
struct UsageRecord {
category: String,
description: String,
account_sid: String,
start_date: String,
end_date: String,
as_of: String,
count: String,
count_unit: String,
usage: String,
usage_unit: String,
price: String,
price_unit: String,
api_version: String,
uri: String,
subresource_uris: SubresourceUris,
}
#[derive(Serialize, Deserialize)]
struct SubresourceUris {
all_time: String,
today: String,
yesterday: String,
this_month: String,
last_month: String,
daily: String,
monthly: String,
yearly: String,
}
impl AccountUsage {
fn get_total_usage_cost(&self, usage_records: &Vec<UsageRecord>) -> f64 {
let mut usage_total = 0.0;
let au_iter = usage_records.iter();
for val in au_iter {
let price: f64 = val.price.parse().unwrap();
usage_total = usage_total + price;
}
return usage_total;
}
fn print_usage_report(&self) {
let data_iter = self.usage_records.iter();
for record in data_iter {
println!(
"{},{},{},{}",
record.start_date, record.end_date, record.category, record.price
);
}
}
}
fn main() -> Result<(), Error> {
dotenv().ok();
let account_sid = env::var("TWILIO_ACCOUNT_SID")
.expect("Twilio Account SID could not be retrieved.");
let auth_token = env::var("TWILIO_AUTH_TOKEN")
.expect("Twilio Auth Token could not be retrieved.");
let page_size = 20;
let request_url = format!(
"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Usage/Records/LastMonth.json?PageSize={page_size}"
);
let client = Client::new();
let response = client
.get(&request_url)
.basic_auth(account_sid, Some(auth_token))
.send()?;
if response.status() != StatusCode::OK {
println!("Received response status: {:?}", response.status())
}
let body_result = response.text();
let body = match body_result {
Ok(result) => result,
Err(error) => panic!("Problem extracting the JSON body content. Reason: {:?}", error),
};
let account_usage: AccountUsage = serde_json::from_str(&body).unwrap();
let usage_total = account_usage
.get_total_usage_cost(&account_usage.usage_records);
println!("Twilio Account Usage");
account_usage.print_usage_report();
println!("Total records: {}", account_usage.page_size);
println!("Total cost: {}", usage_total);
Ok(())
}
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.
Note that some of AccountUsage
's fields can be nullable, being defined as either Option<String>
or Option<u8>
. This is because responses may not contain values for those fields, so they need to be nullable, if necessary.
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.
cargo run
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.
This content originally appeared on Twilio Blog and was authored by Matthew Setter

Matthew Setter | Sciencx (2023-01-25T16:49:16+00:00) How to View Your Twilio Account Usage Using Rust. Retrieved from https://www.scien.cx/2023/01/25/how-to-view-your-twilio-account-usage-using-rust/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.