Vtiger

Struct Vtiger 

Source
pub struct Vtiger { /* private fields */ }
Expand description

Client for interacting with the Vtiger REST API.

This struct provides a high-level interface for making authenticated requests to a Vtiger CRM instance. It handles authentication, request formatting, and response parsing automatically.

§Examples


async fn main() -> Result<(), Box<dyn std::error::Error>> {

    use vtiger_client::Vtiger;

    let vtiger = Vtiger::new(
        "https://your-instance.vtiger.com",
        "your_username",
        "your_access_key"
    );

    // Query records
    let response = vtiger.query("SELECT * FROM Leads LIMIT 10").await?;
    Ok(())
}

§Authentication

Authentication uses the Vtiger username and access key. The access key can be found in your Vtiger user preferences under “My Preferences” > “Security”.

Implementations§

Source§

impl Vtiger

Source

pub fn new(url: &str, username: &str, access_key: &str) -> Self

Creates a new Vtiger API client.

§Arguments
  • url - The base URL of your Vtiger instance (e.g., https://your-instance.vtiger.com)
  • username - Your Vtiger username
  • access_key - Your Vtiger access key (found in My Preferences > Security)
§Examples
use vtiger_client::Vtiger;

let vtiger = Vtiger::new(
    "https://demo.vtiger.com",
    "admin",
    "your_access_key_here"
);
Examples found in repository?
examples/export_data.rs (lines 5-9)
4async fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let vtiger = Vtiger::new(
6        "https://your-instance.vtiger.com",
7        "your_username",
8        "your_access_key",
9    );
10
11    // Export leads with filtering
12    let prefixes: Vec<String> = vec![
13        "Chicago".to_string(),
14        "Seattle".to_string(),
15        "California".to_string(),
16    ];
17    vtiger
18        .export(
19            "Leads",
20            Some(("location", prefixes)),
21            200,
22            3,
23            vec![ExportFormat::Json, ExportFormat::CSV],
24        )
25        .await?;
26
27    println!("Export completed! Check output.json and output.csv");
28    Ok(())
29}
More examples
Hide additional examples
examples/basic_usage.rs (line 5)
4async fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "your_access_key");
6
7    // Get current user info
8    let user_info = vtiger.me().await?;
9    if user_info.success {
10        println!("Authentication successful");
11        println!("User info: {:#?}", user_info.result);
12    } else {
13        println!("Authentication failed: {:?}", user_info.error);
14    }
15
16    // List available modules
17    let modules = vtiger.list_types(&[]).await?;
18    if modules.success {
19        println!("Available modules: {:#?}", modules.result);
20    }
21
22    // Query some data
23    let leads = vtiger.query("SELECT * FROM Leads LIMIT 5").await?;
24    if leads.success {
25        println!("Found {} leads", leads.result.unwrap_or_default().len());
26    }
27
28    Ok(())
29}
Source

pub async fn me(&self) -> Result<VtigerResponse, Error>

Retrieves information about the currently authenticated user.

This method calls the /me endpoint to get details about the user account associated with the provided credentials. It’s useful for verifying authentication and retrieving user-specific information.

§Returns

Returns a Result containing a VtigerResponse with user information on success, or a reqwest::Error if the request fails.

§Examples
use vtiger_client::Vtiger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new(
        "https://demo.vtiger.com",
        "admin",
        "your_access_key",
    );

    let user_info = vtiger.me().await?;
    if user_info.success {
        println!("Authenticated as: {:?}", user_info.result);
    } else {
        eprintln!("Authentication failed: {:?}", user_info.error);
    }
    Ok(())
}
§Errors

This method will return an error if:

  • The network request fails
  • The response cannot be parsed as JSON
  • The server returns an invalid response format
Examples found in repository?
examples/basic_usage.rs (line 8)
4async fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "your_access_key");
6
7    // Get current user info
8    let user_info = vtiger.me().await?;
9    if user_info.success {
10        println!("Authentication successful");
11        println!("User info: {:#?}", user_info.result);
12    } else {
13        println!("Authentication failed: {:?}", user_info.error);
14    }
15
16    // List available modules
17    let modules = vtiger.list_types(&[]).await?;
18    if modules.success {
19        println!("Available modules: {:#?}", modules.result);
20    }
21
22    // Query some data
23    let leads = vtiger.query("SELECT * FROM Leads LIMIT 5").await?;
24    if leads.success {
25        println!("Found {} leads", leads.result.unwrap_or_default().len());
26    }
27
28    Ok(())
29}
Source

pub async fn list_types( &self, query: &[(&str, &str)], ) -> Result<VtigerResponse, Error>

List the available modules and their information

This endpoint returns a list of all of the available modules (like Contacts, Leads, Accounts) available in your vtiger instance. You can optionally filter modules by the types of fields they contain.

#Arguments

  • query: An optional query string to filter the modules by. Common parameters:
  • `(“fieldTypeList”, “null”) or &[]- Return all available modules
  • `(“fieldTypeList”, “picklist”)- Return modules with picklist fields
  • `(“fieldTypeList”, “grid”)- Return modules with grid fields
§Returns

A VtigerResponse containing module information. The result typically includes:

  • types: Array of module names
  • information: Object with detailed info about each module
§Errors

Returns reqwest::Error for network issues or authentication failures. Check the response’s success field and error field for API-level errors.

§Examples
let vtiger = Vtiger::new("https://demo.vtiger.com/", "admin", "access_key");

// Get all available modules
let all_modules = vtiger.list_types(&[("fieldTypeList", "null")]).await?;

// Get modules with picklist fields only
let picklist_modules = vtiger.list_types(&[("fieldTypeList[]", "picklist")]).await?;

// Get all modules (no filtering)
let modules = vtiger.list_types(&[]).await?;

if all_modules.success {
    println!("Available modules: {:#?}", all_modules.result);
}
Examples found in repository?
examples/basic_usage.rs (line 17)
4async fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "your_access_key");
6
7    // Get current user info
8    let user_info = vtiger.me().await?;
9    if user_info.success {
10        println!("Authentication successful");
11        println!("User info: {:#?}", user_info.result);
12    } else {
13        println!("Authentication failed: {:?}", user_info.error);
14    }
15
16    // List available modules
17    let modules = vtiger.list_types(&[]).await?;
18    if modules.success {
19        println!("Available modules: {:#?}", modules.result);
20    }
21
22    // Query some data
23    let leads = vtiger.query("SELECT * FROM Leads LIMIT 5").await?;
24    if leads.success {
25        println!("Found {} leads", leads.result.unwrap_or_default().len());
26    }
27
28    Ok(())
29}
Source

pub async fn describe(&self, module_name: &str) -> Result<VtigerResponse, Error>

List the fields of a module.

This endpoint returns a list of fields, their types, labels, default values, and other metadata of a module.

#Arguments

  • module_name: The name of the module to describe.

#Errors

Returns reqwest::Error for network issues or authentication failures. Check the response’s success field and error field for API-level errors.

#Examples

let vtiger = Vtiger::new("https://demo.vtiger.com/", "admin", "access_key");

// Describe the Accounts module
let accounts_description = vtiger.describe("Accounts").await?;

if accounts_description.success {
    println!("Fields of Accounts module: {:#?}", accounts_description.result);
}
Source

pub async fn export( &self, module: &str, query_filter: Option<(&str, Vec<String>)>, batch_size: usize, concurrency: usize, format: Vec<ExportFormat>, ) -> Result<(), Box<dyn Error>>

Export records from a module to multiple file formats.

This method performs a high-performance, concurrent export of records from a Vtiger module. It automatically handles batching, concurrency, and multiple output formats simultaneously. Be wary of rate limits and potential API throttling.

§Process Overview
  1. Count Phase: Determines record counts for each filter
  2. Batch Phase: Creates work items based on batch size
  3. Concurrent Export: Runs multiple queries in parallel
  4. File Writing: Writes to multiple formats simultaneously
§Arguments
  • module - The Vtiger module name (e.g., “Leads”, “Contacts”, “Accounts”)
  • query_filter - Optional filter as (column_name, filter_values). Uses LIKE queries with ‘-’ suffix
  • batch_size - Number of records per batch (recommended: 100-200)
  • concurrency - Number of concurrent requests (recommended: 2-5)
  • format - Vector of output formats to generate simultaneously
§Output Files
  • JSON: output.json - Single JSON array with all records
  • JSON Lines: output.jsonl - One JSON object per line
  • CSV: output.csv - Traditional CSV with headers
§Performance Notes
  • Vtiger’s query API has an implicit limit of ~100 records per query
  • Batch sizes of 200 may work depending on module and account tier
  • Higher concurrency may hit API rate limits
  • Multiple formats are written simultaneously for efficiency
§Examples
use vtiger_client::{Vtiger, ExportFormat};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "key");

    // Export all leads
    vtiger.export(
        "Leads",
        None,
        200,
        3,
        vec![ExportFormat::Json, ExportFormat::CSV]
    ).await?;

    // Export leads with specific locations
    let locations = vec!["Los Angeles".to_string(), "Seattle".to_string()];
    vtiger.export(
        "Leads",
        Some(("Location", locations)),
        200,
        3,
        vec![ExportFormat::JsonLines]
    ).await?;

    Ok(())
}
§Errors

Returns an error if:

  • Network requests fail
  • File creation fails
  • JSON serialization fails
  • Invalid module name or query syntax
Examples found in repository?
examples/export_data.rs (lines 18-24)
4async fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let vtiger = Vtiger::new(
6        "https://your-instance.vtiger.com",
7        "your_username",
8        "your_access_key",
9    );
10
11    // Export leads with filtering
12    let prefixes: Vec<String> = vec![
13        "Chicago".to_string(),
14        "Seattle".to_string(),
15        "California".to_string(),
16    ];
17    vtiger
18        .export(
19            "Leads",
20            Some(("location", prefixes)),
21            200,
22            3,
23            vec![ExportFormat::Json, ExportFormat::CSV],
24        )
25        .await?;
26
27    println!("Export completed! Check output.json and output.csv");
28    Ok(())
29}
Source

pub async fn create( &self, module_name: &str, fields: &[(&str, &str)], ) -> Result<VtigerResponse, Box<dyn Error>>

Create a new record in the specified module.

This method creates a single record in Vtiger by sending field data to the /create endpoint. The fields are automatically serialized to JSON format as required by the Vtiger API.

§Arguments
  • module_name - The name of the module to create the record in
  • fields - Array of field name/value pairs to set on the new record
§Returns

Returns a VtigerResponse containing the created record’s ID and data on success, or the error details on failure.

§Examples
use vtiger_client::Vtiger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "key");

    // Create a new lead
    let response = vtiger.create(
        "Leads",
        &[
            ("lastname", "Smith"),
            ("firstname", "John"),
            ("email", "john.smith@example.com"),
            ("company", "Acme Corp"),
        ]
    ).await?;

    if response.success {
        println!("Created record: {:?}", response.result);
    } else {
        eprintln!("Creation failed: {:?}", response.error);
    }

    Ok(())
}
§Errors

This method will return an error if:

  • The network request fails
  • The response cannot be parsed as JSON
  • Invalid module name or field names are provided
  • Required fields are missing (check API response for details)
Source

pub async fn retrieve(&self, record_id: &str) -> Result<VtigerResponse, Error>

Retrieve a single record by its ID.

This method fetches a complete record from Vtiger using its unique ID. The ID should be in Vtiger’s format (e.g., “12x34” where 12 is the module ID and 34 is the record ID).

§Arguments
  • record_id - The Vtiger record ID (format: “ModuleIDxRecordID”)
§Returns

Returns a VtigerResponse containing the record data on success, or error details on failure.

§Examples
use vtiger_client::Vtiger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "key");

    // Retrieve a specific lead record
    let response = vtiger.retrieve("12x34").await?;

    if response.success {
        if let Some(record) = response.result {
            println!("Record data: {:#?}", record);
            // Access specific fields
            if let Some(name) = record.get("lastname") {
                println!("Last name: {}", name);
            }
        }
    } else {
        eprintln!("Retrieval failed: {:?}", response.error);
    }

    Ok(())
}
§Record ID Format

Vtiger record IDs follow the format “ModuleIDxRecordID”:

  • 12x34 - Module 12, Record 34
  • 4x567 - Module 4, Record 567

You can typically get these IDs from:

  • Previous create/query operations
  • The Vtiger web interface URL
  • Other API responses
§Errors

This method will return an error if:

  • The network request fails
  • The response cannot be parsed as JSON
  • The record ID format is invalid
  • The record doesn’t exist or you don’t have permission to view it
Source

pub async fn query(&self, query: &str) -> Result<VtigerQueryResponse, Error>

Execute a SQL-like query against Vtiger data.

This method allows you to query Vtiger records using a SQL-like syntax. It returns multiple records and is the primary method for searching and filtering data in Vtiger.

§Arguments
  • query - SQL-like query string using Vtiger’s query syntax
§Returns

Returns a VtigerQueryResponse containing an array of matching records on success, or error details on failure.

§Query Syntax

Vtiger supports a subset of SQL:

  • SELECT * FROM ModuleName
  • SELECT field1, field2 FROM ModuleName
  • WHERE conditions with =, !=, LIKE, IN
  • ORDER BY for sorting
  • LIMIT for pagination (recommended: ≤200 records)
§Examples
use vtiger_client::Vtiger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "key");

    // Basic query
    let response = vtiger.query("SELECT * FROM Leads LIMIT 10").await?;

    // Query with conditions
    let response = vtiger.query(
        "SELECT firstname, lastname, email FROM Leads WHERE email != ''"
    ).await?;

    // Query with LIKE operator
    let response = vtiger.query(
        "SELECT * FROM Leads WHERE lastname LIKE 'Smith%'"
    ).await?;

    // Query with ordering
    let response = vtiger.query(
        "SELECT * FROM Leads ORDER BY createdtime DESC LIMIT 50"
    ).await?;

    if response.success {
        if let Some(records) = response.result {
            println!("Found {} records", records.len());
            for record in records {
                println!("Record: {:#?}", record);
            }
        }
    } else {
        eprintln!("Query failed: {:?}", response.error);
    }

    Ok(())
}
§Performance Considerations
  • Limit results: Always use LIMIT to avoid timeouts
  • Batch large queries: Use pagination for large datasets
  • Index usage: Filter on indexed fields when possible
  • Concurrent queries: Use multiple queries for better performance
§Common Query Patterns
-- Get recent records
SELECT * FROM Leads ORDER BY createdtime DESC LIMIT 100

-- Filter by custom field
SELECT * FROM Leads WHERE location LIKE 'Los Angeles%'

-- Count records
SELECT count(*) FROM Leads WHERE leadstatus = 'Hot'

-- Multiple conditions
SELECT * FROM Leads WHERE email != '' AND leadstatus IN ('Hot', 'Warm')
§Errors

This method will return an error if:

  • The network request fails
  • The response cannot be parsed as JSON
  • Invalid SQL syntax is used
  • Referenced fields or modules don’t exist
  • Query exceeds time or result limits
Examples found in repository?
examples/basic_usage.rs (line 23)
4async fn main() -> Result<(), Box<dyn std::error::Error>> {
5    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "your_access_key");
6
7    // Get current user info
8    let user_info = vtiger.me().await?;
9    if user_info.success {
10        println!("Authentication successful");
11        println!("User info: {:#?}", user_info.result);
12    } else {
13        println!("Authentication failed: {:?}", user_info.error);
14    }
15
16    // List available modules
17    let modules = vtiger.list_types(&[]).await?;
18    if modules.success {
19        println!("Available modules: {:#?}", modules.result);
20    }
21
22    // Query some data
23    let leads = vtiger.query("SELECT * FROM Leads LIMIT 5").await?;
24    if leads.success {
25        println!("Found {} leads", leads.result.unwrap_or_default().len());
26    }
27
28    Ok(())
29}
Source

pub async fn update( &self, fields: &Vec<(&str, &str)>, ) -> Result<VtigerResponse, Box<dyn Error>>

Update a record in the database

This function takes a single record that must include an ID and all required fields on the module in order to successfulyy update the record. It’s recommended to use the revise function instead of this one.

§Arguments
  • fields - A vector of tuples containing the field name and value to update.
§Returns

Returns a VtigerResponse containing a message indicating success or failure, and the result if successful.

§Examples
use vtiger_client::Vtiger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "key");

    // Query with conditions
    let update_fields = vec![
        ("id", "2x12345"),
        ("first_name", "John"),
        ("last_name", "Smith"),
        ("email", "smith@example.com"),
        ("phone", "604-555-1212"),
        ("lane", "123 Main St"),
        ("city", "Los Angeles"),
        ("state", "CA"),
        ("postal_code", "12345"),
    ];
    let response = vtiger.update(&update_fields).await?;

    println!("Updated record: {:?}", response);
    Ok(())
}
Source

pub async fn revise( &self, fields: &Vec<(&str, &str)>, ) -> Result<VtigerResponse, Box<dyn Error>>

Update a record in the database

This function takes a single record that must include an ID and at least one field to update.

§Arguments
  • fields - A vector of tuples containing the field name and value to update.
§Returns

Returns a VtigerResponse containing a message indicating success or failure, and the result if successful.

§Examples
use vtiger_client::Vtiger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let vtiger = Vtiger::new("https://demo.vtiger.com", "admin", "key");

    // Query with conditions
    let update_fields = vec![
        ("id", "2x12345"),
        ("phone", "604-555-1212"),
    ];
    let response = vtiger.revise(&update_fields).await?;

    println!("Updated record: {:?}", response);
    Ok(())
}

Trait Implementations§

Source§

impl Debug for Vtiger

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Vtiger

§

impl !RefUnwindSafe for Vtiger

§

impl Send for Vtiger

§

impl Sync for Vtiger

§

impl Unpin for Vtiger

§

impl !UnwindSafe for Vtiger

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,