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, 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}

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,