Rust Client
The datto-api crate provides an async Rust client for the Datto RMM API.
Installation
Section titled “Installation”Add to your Cargo.toml:
[dependencies]datto-api = { path = "path/to/datto-rmm/crates/datto-api" }tokio = { version = "1", features = ["rt-multi-thread", "macros"] }Quick Start
Section titled “Quick Start”use datto_api::{DattoClient, Platform, Credentials};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let client = DattoClient::new( Platform::Merlot, Credentials { api_key: std::env::var("DATTO_API_KEY")?, api_secret: std::env::var("DATTO_API_SECRET")?, }, ).await?;
println!("Connected to {}", client.platform()); println!("Base URL: {}", client.base_url());
Ok(())}Platforms
Section titled “Platforms”Choose the platform that matches your Datto RMM account:
use datto_api::Platform;
// Available platformslet platforms = [ Platform::Pinotage, // https://pinotage-api.centrastage.net/api Platform::Merlot, // https://merlot-api.centrastage.net/api Platform::Concord, // https://concord-api.centrastage.net/api Platform::Vidal, // https://vidal-api.centrastage.net/api Platform::Zinfandel, // https://zinfandel-api.centrastage.net/api Platform::Syrah, // https://syrah-api.centrastage.net/api];
// Get the base URLlet url = Platform::Merlot.base_url();// => "https://merlot-api.centrastage.net/api"
// Parse from stringlet platform: Platform = "merlot".parse()?;Authentication
Section titled “Authentication”The client automatically handles OAuth 2.0 token management:
use datto_api::{DattoClient, Platform, Credentials};
let client = DattoClient::new( Platform::Merlot, Credentials { api_key: "your-api-key".into(), api_secret: "your-api-secret".into(), },).await?;
// Tokens are managed automatically// - Cached in memory// - Refreshed 5 minutes before expiry// - Thread-safe (uses RwLock internally)
// You can manually get a token if neededlet token = client.ensure_token().await?;Error Handling
Section titled “Error Handling”The client provides typed errors:
use datto_api::Error;
async fn example(client: &DattoClient) { match some_operation().await { Ok(result) => { println!("Success: {:?}", result); } Err(Error::Auth(msg)) => { // Authentication failed (invalid credentials, token expired, etc.) eprintln!("Authentication failed: {}", msg); } Err(Error::HttpClient(e)) => { // Network or HTTP client error eprintln!("HTTP error: {}", e); } Err(Error::Api { status, message }) => { // API returned an error response eprintln!("API error {}: {}", status, message); } }}Generated Types
Section titled “Generated Types”The Rust client generates types from the OpenAPI spec at build time using progenitor.
When the spec is available, types are exported from the crate:
// These types will be available when compiled with the OpenAPI specuse datto_api::types::{Device, Alert, Site};Building
Section titled “Building”The crate uses a build script to generate code from the OpenAPI spec:
# Ensure the spec existspnpm sync:openapi
# Build the cratecargo build -p datto-api
# Run testscargo test -p datto-apiMaking Custom Requests
Section titled “Making Custom Requests”For endpoints not covered by the generated client, use the HTTP client directly:
use datto_api::{DattoClient, Platform, Credentials};
let client = DattoClient::new( Platform::Merlot, Credentials { api_key: "...".into(), api_secret: "...".into() },).await?;
// Get a valid tokenlet token = client.ensure_token().await?;
// Make a custom requestlet response = client .http_client() .get(format!("{}/v2/custom/endpoint", client.base_url())) .header("Authorization", format!("Bearer {}", token)) .send() .await?;Dependencies
Section titled “Dependencies”The crate uses:
reqwestwithrustls-tlsfor HTTP requeststokiofor async runtimeserdefor serializationthiserrorfor error handlingprogenitorfor code generation (build-time)