# Generate a Rust client for Twilio's API

With the rollout of [Twilio's OpenAPI specification][], it is now possible to auto-generate your own Twilio client in your preferred programming language.

One language that Twilio currently does not have an official SDK for is Rust. By using the Twilio OpenAPI specification with open source tools such as [OpenAPI Generator][], you can now generate a strongly-typed Rust client for Twilio's API methods.

## Setup

To begin, [install][] OpenAPI Generator. If you are on a Mac, we recommend installing using Homebrew for ease of use as below:

```bash
brew install openapi-generator
```

Once OpenAPI Generator is installed, the next step is to generate your very first Twilio client in Rust. Paste the following code snippet into your terminal to pull in the Twilio OpenAPI spec from GitHub, generate a client, and save the resulting client code to a directory named `twilio-rust`.

```bash
openapi-generator generate -g rust \
  -i https://raw.githubusercontent.com/twilio/twilio-oai/main/spec/json/twilio_api_v2010.json \
  -o twilio-rust \
  --additional-properties=useSingleRequestParameter=true
```

> \[!NOTE]
>
> To see other ways you can customize the generated library to your needs, see the [configuration documentation][] for the Rust generator.

## Use the auto-generated Twilio Rust client

### Create a Rust project

Now that the client has been generated, it's time to create some code that will enable you to interact with Twilio's API in Rust. If you don't already have Rust installed, you can [install Rust][] by following the instructions as described in their documentation.

With Rust installed, create a new Rust project. We suggest that you use `cargo` to simplify this process and run the following command from the same directory where you executed the codegen process:

```bash
cargo new twilio-rust-example
```

This will scaffold out a Rust project for you, with the necessary `main.rs` file and a `Cargo.toml` file for managing dependencies.

```bash
.
├── src
│   └── main.rs
└── Cargo.toml
```

### Add dependencies

In order to make use of the generated Twilio client, it must be added to the project's `Cargo.toml`. More specifically, it should be added as a [path dependency][], since it is a crate currently residing on your local file system instead of [crates.io][] or a similar repository.

Let's add two more dependencies as well:

* `dotenv` to enable access to environment variables from a local `.env` file
* `tokio` which provides an asynchronous runtime environment so that your code can use `async/await`

You can manually edit `Cargo.toml` to include these dependencies, but we suggest leveraging a tool such as [cargo-edit][] to manage dependencies. Once you have installed `cargo-edit`, run the following commands:

```bash
cargo add openapi --path=../twilio-rust
cargo add dotenv
cargo add tokio --features rt,rt-multi-thread,macros
```

Once `cargo-edit` has completed (or you skipped that step and did things manually), `Cargo.toml` will reflect the following contents:

```toml
[package]
name = "twilio-rust-example"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dotenv = "0.15.0"
openapi = { path = "../twilio-rust" }
tokio = { version = "1.21.1", features = ["rt", "rt-multi-thread", "macros"] }
```

> \[!NOTE]
>
> The specific versions of `dotenv` and `tokio` may vary from this example depending on when you are coming across this tutorial. Using `cargo-edit` as shown above will ensure you're on the latest version of each.

Once you've saved those changes to `Cargo.toml`, run the following command to install all of the above dependencies.

```bash
cargo build
```

### Send an SMS using Twilio and Rust

Now that our dependencies are in order, it's time to create a program in Rust.

We will leverage environment variables in order to securely access your Twilio credentials, so the next step is to create a `.env` file at the root of your Rust project and provide the necessary values. Be sure to replace the placeholder values here with your own credentials and a non-Twilio phone number such as your own as `TO_NUMBER`. Ensure that your phone numbers are declared in the [E.164 format][] (+1234567890).

```bash
TWILIO_API_KEY=SKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TWILIO_API_KEY_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TWILIO_PHONE_NUMBER=+1098765432
TO_NUMBER=+1234567890
```

> \[!NOTE]
>
> Note that we're using best practices here, and creating the Twilio client using an API Key and Secret instead of directly using and potentially exposing your account's auth token. If you'd like to learn more about API Keys and how to create one, see the [API Keys][] documentation!

With the environment variables in place, it's time to open `src/main.rs` and replace the boilerplate code there with the following sample:

```rust title="Send an SMS with Rust"
use dotenv;
use openapi::apis::{
    configuration::Configuration,
    default_api::{self as twilio_api, CreateMessageParams},
};
use std::env;

#[tokio::main]
async fn main() {
    // Securely import sensitive credentials and values from your .env file
    dotenv::dotenv().expect("Failed to read .env file");
    let account_sid = env::var("TWILIO_ACCOUNT_SID")
        .expect("env variable `TWILIO_ACCOUNT_SID` should be set");
    let api_key = env::var("TWILIO_API_KEY")
        .expect("env variable `TWILIO_API_KEY` should be set");
    let api_key_secret = env::var("TWILIO_API_KEY_SECRET")
        .expect("env variable `TWILIO_API_KEY_SECRET` should be set");
    let from = env::var("TWILIO_PHONE_NUMBER")
        .expect("env variable `TWILIO_PHONE_NUMBER` should be set");
    let to = env::var("TO_NUMBER").expect("env variable `TO_NUMBER` should be set");

    // Create a new configuration for your Twilio client.
    let twilio_config = Configuration {
        basic_auth: Some((api_key, Some(api_key_secret))),
        ..Default::default()
    };

    // Define the message that you wish to send
    let message_params = CreateMessageParams {
        account_sid,
        to,
        from: Some(from),
        body: Some("Ahoy, Rustacean! 🦀".into()),
        ..Default::default()
    };

    // Asynchronously send the message from your Twilio phone number.
    let message = twilio_api::create_message(&twilio_config, message_params).await;

    match message {
        Ok(result) => {
            println!("Message sent with SID {}", result.sid.unwrap().unwrap())
        }
        Err(error) => eprintln!("Error sending message: {}", error),
    };
}

```

Execute `cargo run` in your terminal, and you will see a log output of the message's SID as well as an SMS appear on your intended phone shortly after.

```bash
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/twilio-rust-example`
Message sent with SID "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
```

[API Keys]: /docs/iam/api-keys/key-resource-v2010

[cargo-edit]: https://github.com/killercup/cargo-edit#cargo-edit

[configuration documentation]: https://openapi-generator.tech/docs/generators/rust

[crates.io]: https://crates.io

[E.164 format]: /docs/glossary/what-e164

[install Rust]: https://www.rust-lang.org/tools/install

[install]: https://openapi-generator.tech/docs/installation

[OpenAPI Generator]: https://openapi-generator.tech

[path dependency]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-path-dependencies

[Twilio's OpenAPI specification]: https://github.com/twilio/twilio-oai
