Airtable API API in Rust
Airtable API API in Rust
This guide shows you how to integrate the Airtable API into your Rust application. Spreadsheet-database hybrid API with CRUD on bases, records, and attachments.
Prerequisites
- Rust installed on your system
- An Airtable API API key (sign up at https://airtable.com/developers/web/api)
- Basic familiarity with HTTP APIs
Installation
cargo add reqwest --features json
cargo add tokio --features full
Basic Usage
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("API_KEY").unwrap_or_else(|_| "YOUR_API_KEY".to_string());
let base_url = "https://api.airtable.com";
let url = format!("{}/v1/resources", base_url);
let client = reqwest::Client::new();
let resp = client
.get(&url)
.bearer_auth(&api_key)
.header("Content-Type", "application/json")
.send()
.await?;
println!("Status: {}", resp.status());
let body = resp.text().await?;
println!("{}", body);
Ok(())
}
Error Handling
use std::time::Duration;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("API_KEY").unwrap_or_else(|_| "YOUR_API_KEY".to_string());
let base_url = "https://api.airtable.com";
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut attempt = 0;
let max_retries = 3;
loop {
let resp = client
.get(format!("{}/v1/resources", base_url))
.bearer_auth(&api_key)
.send()
.await?;
if resp.status().as_u16() == 429 {
println!("Rate limited. Waiting 60s...");
tokio::time::sleep(Duration::from_secs(60)).await;
continue;
}
if resp.status().is_success() {
let body = resp.text().await?;
println!("{}", body);
return Ok(());
}
attempt += 1;
if attempt >= max_retries {
return Err(format!("HTTP {}", resp.status()).into());
}
tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await;
}
}
Advanced Usage
use std::env;
use reqwest::{Client, Method};
use std::error::Error;
pub struct AirtableClient {
client: Client,
api_key: String,
base_url: String,
}
impl AirtableClient {
pub fn new(api_key: String, base_url: String) -> Self {
Self {
client: Client::new(),
api_key,
base_url: base_url.trim_end_matches('/').to_string(),
}
}
pub async fn request(&self, method: Method, path: &str) -> Result<String, Box<dyn Error>> {
let url = format!("{}/v1{}", self.base_url, path);
let resp = self.client
.request(method, &url)
.bearer_auth(&self.api_key)
.header("Content-Type", "application/json")
.send()
.await?;
if !resp.status().is_success() {
return Err(format!("API Error: HTTP {}", resp.status()).into());
}
Ok(resp.text().await?)
}
pub async fn list_resources(&self) -> Result<String, Box<dyn Error>> {
self.request(Method::GET, "/resources").await
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = AirtableClient::new(
env::var("API_KEY")?,
"https://api.airtable.com".to_string(),
);
let resources = client.list_resources().await?;
println!("{}", resources);
Ok(())
}
Best Practices
- Store your API key in an environment variable, never in source code
- Implement retry logic with exponential backoff for 429 and 5xx errors
- Set reasonable timeouts (10-30 seconds) for all API calls
- Log request IDs from response headers for debugging
- Cache responses where appropriate to reduce API calls