appwrite/skills

appwrite-rust

Appwrite Rust SDK skill.

View source
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Appwrite Rust SDK

Installation

bash
cargo add appwrite
cargo add tokio --features full
cargo add serde_json

Or add dependencies manually:

toml
[dependencies]
appwrite = "0.3.0"
tokio = { version = "1", features = ["full"] }
serde_json = "1"

Setting Up the Client

The Rust SDK is async. Use it from a Tokio runtime and authenticate server-side with an API key.

rust
use appwrite::Client;
use std::env;

let client = Client::new()
    .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")
    .set_project(env::var("APPWRITE_PROJECT_ID")?)
    .set_key(env::var("APPWRITE_API_KEY")?);

Complete server skeleton

rust
use appwrite::query::Query;
use appwrite::services::Users;
use appwrite::Client;
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new()
        .set_endpoint("https://<REGION>.cloud.appwrite.io/v1")
        .set_project(env::var("APPWRITE_PROJECT_ID")?)
        .set_key(env::var("APPWRITE_API_KEY")?);

    let users = Users::new(&client);
    let _list = users
        .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))
        .await?;

    Ok(())
}

Code Examples

User Management

rust
use appwrite::id::ID;
use appwrite::query::Query;
use appwrite::services::Users;

let users = Users::new(&client);

// Create user
let _user = users
    .create(
        ID::unique(),
        Some("user@example.com"),
        None,
        Some("password123"),
        Some("User Name"),
    )
    .await?;

// List users
let _list = users
    .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))
    .await?;

// Get user
let _fetched = users.get("[USER_ID]").await?;

// Delete user
users.delete("[USER_ID]").await?;

Database Operations

Note: Use TablesDB for new code. Only use Databases if the existing project explicitly depends on the legacy Databases API. Rust SDK calling convention: Methods are async, use positional parameters, and represent optional API parameters as Option<T>. Pass None for optional values you are not setting.
rust
use appwrite::id::ID;
use appwrite::permission::Permission;
use appwrite::query::Query;
use appwrite::role::Role;
use appwrite::services::TablesDB;
use serde_json::json;

let tables_db = TablesDB::new(&client);

// Create database
let _database = tables_db
    .create(ID::unique(), "My Database", Some(true))
    .await?;

// Create table
let _table = tables_db
    .create_table(
        "[DATABASE_ID]",
        ID::unique(),
        "articles",
        Some(vec![
            Permission::read(Role::any()).to_string(),
            Permission::create(Role::users(None)).to_string(),
        ]),
        Some(true),
        Some(true),
        None,
        None,
    )
    .await?;

// Create row
let _row = tables_db
    .create_row(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        ID::unique(),
        json!({
            "title": "Hello World",
            "done": false
        }),
        None,
        None,
    )
    .await?;

// Query rows
let _rows = tables_db
    .list_rows(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        Some(vec![
            Query::equal("done", false).to_string(),
            Query::limit(10).to_string(),
        ]),
        None,
        Some(true),
        None,
    )
    .await?;

// Get row
let _row = tables_db
    .get_row("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]", None, None)
    .await?;

// Update row
let _updated = tables_db
    .update_row(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        "[ROW_ID]",
        Some(json!({ "done": true })),
        None,
        None,
    )
    .await?;

// Delete row
tables_db
    .delete_row("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]", None)
    .await?;

String Column Types

Note: The legacy string column type is deprecated. Use explicit string column types for new tables.
TypeMax charactersIndexingStorage
varchar16,383Full index (if size <= 768)Inline in row
text16,383Prefix onlyOff-page
mediumtext4,194,303Prefix onlyOff-page
longtext1,073,741,823Prefix onlyOff-page
  • varchar is stored inline and counts toward the 64 KB row size limit. Prefer it for short, indexed fields like names, slugs, and identifiers.
  • text, mediumtext, and longtext are stored off-page, so they do not consume the row size budget. size is not required for these types.
rust
use appwrite::enums::{OrderBy, TablesDBIndexType};

// Short, indexed string
let _title = tables_db
    .create_varchar_column(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        "title",
        255,
        true,
        None,
        None,
        None,
    )
    .await?;

// Off-page longer text
let _summary = tables_db
    .create_text_column("[DATABASE_ID]", "[TABLE_ID]", "summary", false, None, None, None)
    .await?;

let _body = tables_db
    .create_mediumtext_column("[DATABASE_ID]", "[TABLE_ID]", "body", false, None, None, None)
    .await?;

let _raw_data = tables_db
    .create_longtext_column("[DATABASE_ID]", "[TABLE_ID]", "raw_data", false, None, None, None)
    .await?;

// Index only the varchar column fully.
let _index = tables_db
    .create_index(
        "[DATABASE_ID]",
        "[TABLE_ID]",
        "title_idx",
        TablesDBIndexType::Key,
        vec!["title"],
        Some(vec![OrderBy::Asc]),
        Some(vec![255]),
    )
    .await?;

Query Methods

TablesDB methods accept Option<Vec<String>> for queries. Convert each Query to a string.

rust
use appwrite::query::Query;
use serde_json::Value;

let queries = vec![
    Query::equal("status", "published").to_string(),
    Query::not_equal("archived", true).to_string(),
    Query::greater_than("views", 100).to_string(),
    Query::less_than_equal("priority", 5).to_string(),
    Query::between("score", 1, 100).to_string(),
    Query::is_not_null("publishedAt").to_string(),
    Query::search("title", "rust appwrite").to_string(),
    Query::contains("tags", "rust").to_string(),
    Query::order_desc("$createdAt").to_string(),
    Query::limit(25).to_string(),
    Query::offset(50).to_string(),
];

let multi_value = Query::equal(
    "status",
    Value::Array(vec![
        Value::String("draft".to_string()),
        Value::String("published".to_string()),
    ]),
)
.to_string();

File Storage

rust
use appwrite::id::ID;
use appwrite::input_file::InputFile;
use appwrite::permission::Permission;
use appwrite::query::Query;
use appwrite::role::Role;
use appwrite::services::Storage;

let storage = Storage::new(&client);

// Create bucket
let _bucket = storage
    .create_bucket(
        ID::unique(),
        "Uploads",
        Some(vec![
            Permission::read(Role::any()).to_string(),
            Permission::create(Role::users(None)).to_string(),
        ]),
        Some(true),
        Some(true),
        Some(30_000_000),
        Some(vec!["jpg".to_string(), "png".to_string(), "pdf".to_string()]),
        None,
        Some(true),
        Some(true),
        Some(true),
    )
    .await?;

// Upload from disk
let input = InputFile::from_path("avatar.png", Some("image/png")).await?;
let _file = storage
    .create_file(
        "[BUCKET_ID]",
        ID::unique(),
        input,
        Some(vec![Permission::read(Role::any()).to_string()]),
    )
    .await?;

// Upload from bytes
let input = InputFile::from_bytes(b"hello".to_vec(), "hello.txt", Some("text/plain"));
let _file = storage.create_file("[BUCKET_ID]", ID::unique(), input, None).await?;

// List files
let _files = storage
    .list_files("[BUCKET_ID]", Some(vec![Query::limit(10).to_string()]), None, Some(true))
    .await?;

// Download file bytes
let _content = storage
    .get_file_download("[BUCKET_ID]", "[FILE_ID]", None)
    .await?;

// Delete file
storage.delete_file("[BUCKET_ID]", "[FILE_ID]").await?;

Functions

rust
use appwrite::enums::ExecutionMethod;
use appwrite::query::Query;
use appwrite::services::Functions;
use serde_json::json;

let functions = Functions::new(&client);

// List functions
let _functions = functions
    .list(Some(vec![Query::limit(25).to_string()]), None, Some(true))
    .await?;

// Execute function
let _execution = functions
    .create_execution(
        "[FUNCTION_ID]",
        Some(r#"{"hello":"world"}"#),
        Some(false),
        Some("/jobs/sync"),
        Some(ExecutionMethod::POST),
        Some(json!({ "content-type": "application/json" })),
        None,
    )
    .await?;

// Get execution
let _execution = functions
    .get_execution("[FUNCTION_ID]", "[EXECUTION_ID]")
    .await?;

Permissions

rust
use appwrite::permission::Permission;
use appwrite::role::Role;

let permissions = vec![
    Permission::read(Role::any()).to_string(),
    Permission::create(Role::users(None)).to_string(),
    Permission::update(Role::user("[USER_ID]", None)).to_string(),
    Permission::delete(Role::team("[TEAM_ID]", Some("owner"))).to_string(),
];

Error Handling

rust
match users.get("[USER_ID]").await {
    Ok(user) => {
        let _user = user;
    }
    Err(error) if error.status_code() == 404 => {
        eprintln!("User not found: {}", error.get_message());
    }
    Err(error) => {
        eprintln!("Appwrite error {}: {}", error.status_code(), error.get_message());
        return Err(Box::new(error) as Box<dyn std::error::Error>);
    }
}

Common Pitfalls

  • The Rust SDK is currently a server-side SDK. Prefer TypeScript/Web, Flutter, Apple, Android, or React Native SDKs for browser/mobile client auth flows.
  • Always await service calls.
  • Pass None for optional parameters you are not using.
  • Use TablesDB, not legacy Databases, for new database code.
  • Convert queries with .to_string() before passing them to APIs that expect Option<Vec<String>>.
  • Use serde_json::json!({...}) for row data and JSON bodies.
  • Use InputFile::from_path(...).await? or InputFile::from_bytes(...) for uploads.
from this repository

More skills

All skills
appwrite
Community

appwrite-ruby

Appwrite Ruby SDK skill. Use when building server-side Ruby applications with Appwrite, including Rails and Sinatra integrations. Covers user management, database/table CRUD, file storage, and functions via API keys.

installs
1
GitHub stars
28
Updated
Aug 18
appwrite
Community

appwrite-cli

How to use the Appwrite CLI well. Covers when to use appwrite.config.json vs appwrite client, pull/push vs one-shot service calls, type-safe SDK and model generation, query flags, CI auth, Cloud regional endpoints, function/site variables, and traps that --help will not mention. Does not catalog commands — run appwrite --help for flags. Use whenever running appwrite, deploying or pulling functions/sites/tables, generating application code from a table schema, initializing or linking a project, s

installs
2
GitHub stars
27
Updated
Aug 18
appwrite
Community

appwrite-dart

Appwrite Dart SDK skill. Use when building Flutter apps (mobile, web, desktop) or server-side Dart applications with Appwrite. Covers client-side auth (email, OAuth), database queries, file uploads with native file handling, real-time subscriptions, and server-side admin via API keys for user management, database administration, storage, and functions.

installs
2
GitHub stars
27
Updated
Aug 18
appwrite
Community

appwrite-dotnet

Appwrite .NET SDK skill. Use when building server-side C or .NET applications with Appwrite, including ASP.NET and Blazor integrations. Covers user management, database/table CRUD, file storage, and functions via API keys.

installs
2
GitHub stars
27
Updated
Aug 18