The quickbooks-types crate provides strongly typed Rust models for QuickBooks Online (QBO) API entities and report types. It focuses on data structures, validation helpers, and report parameter builders. Network access and API calls are intentionally out of scope—use your preferred HTTP client alongside these types.
- Crate: quickbooks-types
- Version: 0.1.1
- License: MIT
QuickBooks API docs: https://developer.intuit.com/app/developer/qbo/docs/get-started
This crate:
- Defines data models for common QBO entities (e.g., Invoice, Customer, Vendor, Item, etc.)
- Provides traits that capture operation preconditions such as can_create, can_full_update, can_sparse_update, etc.
- Includes helper types for lines, references, taxes, contact info, and metadata
- Implements a reports module with rich report parameter builders and types
- Offers optional ergonomics via a builder feature, and an optional reports+Polars integration feature
This crate does not:
- Make HTTP requests
- Provide an async runtime or HTTP client
- Offer a general SQL-like query builder for QBO entities
[dependencies]
quickbooks-types = "0.1.1"Optional features:
- builder: derive Builder types and add convenience constructors for top-level entities
- polars: enable report parsing helpers that integrate with Polars (exposes
reports::QBPolarsError)
Examples:
[dependencies]
quickbooks-types = { version = "0.1.1", features = ["builder"] }
# or
quickbooks-types = { version = "0.1.1", features = ["polars"] }- Entities re-exported at crate root:
- Account, Attachable, Bill, BillPayment, CompanyInfo, Customer, Employee, Estimate, Invoice, Item, Payment, Preferences, SalesReceipt, Vendor
- Nested modules:
common: shared value types (e.g.,NtRef,MetaData, contact and address types, taxes)reports: report data structures and parameter buildersreports::types: report enum-like structs and<Report>Paramsreports::params: reusable parameter enums and typed IDsreports::models: report models (e.g.,Report,Row,ColData)reports::polars(feature = "polars"): Polars integration
Basic construction and serialization of an invoice:
use chrono::NaiveDate;
use serde_json;
use quickbooks_types::{Invoice, Line, LineDetail, SalesItemLineDetail};
use quickbooks_types::common::NtRef;
// minimal invoice with one sales item line
let invoice = Invoice {
customer_ref: Some(NtRef::from(("John Doe", "CUST-123"))),
txn_date: NaiveDate::from_ymd_opt(2024, 10, 1),
line: Some(vec![
Line {
amount: Some(100.0),
line_detail: LineDetail::SalesItemLineDetail(SalesItemLineDetail {
item_ref: Some(NtRef::from(("Widget A", "ITEM-001"))),
qty: Some(1.0),
unit_price: Some(100.0),
..Default::default()
}),
..Default::default()
}
]),
..Default::default()
};
let json = serde_json::to_string_pretty(&invoice).unwrap();
println!("{json}");Operation checks (traits):
use quickbooks_types::{Invoice, QBCreatable, QBReadable, QBDeletable, QBFullUpdatable};
let mut invoice = Invoice::default();
assert!(!invoice.can_create()); // missing required fields (customer_ref + line)
invoice.customer_ref = Some(("John Doe", "CUST-123").into());
invoice.line = Some(vec![]);
assert!(!invoice.can_create()); // line must be a non-empty collection with amounts
// simulate entity read from QBO
invoice.id = Some("123".into());
invoice.sync_token = Some("2".into());
assert!(invoice.can_read()); // ID is set
assert!(!invoice.can_full_update()); // still fails creation rules
// deletion requires "has_read" (ID + sync_token)
assert!(invoice.can_delete());Convert entities to references (NtRef):
use quickbooks_types::{Customer, QBToRef};
let mut customer = Customer::default();
customer.id = Some("CUST-123".into());
customer.display_name = Some("John Doe".into());
let customer_ref = customer.to_ref().unwrap();
// customer_ref.name == Some("John Doe"), customer_ref.value == Some("CUST-123")Enable the builder feature to get derived builders for most entity types and a convenience ::new() associated function for top-level entities (e.g., Invoice::new() returns an InvoiceBuilder).
[dependencies]
quickbooks-types = { version = "0.1.1", features = ["builder"] }use chrono::NaiveDate;
use quickbooks_types::common::NtRef;
use quickbooks_types::{Invoice, LineDetail, QBCreatable};
use quickbooks_types::{LineBuilder, SalesItemLineDetailBuilder};
let invoice = Invoice::new()
.customer_ref(NtRef::from(("John Doe", "CUST-123")))
.txn_date(NaiveDate::from_ymd_opt(2024, 10, 1).unwrap())
.line(vec![
LineBuilder::default()
.amount(100.0)
.line_detail(LineDetail::SalesItemLineDetail(
SalesItemLineDetailBuilder::default()
.item_ref(NtRef::from(("Widget A", "ITEM-001")))
.qty(1.0)
.unit_price(100.0)
.build()
.unwrap(),
))
.build()
.unwrap(),
])
.build()
.unwrap();
assert!(invoice.can_create());Attachable convenience (builder):
use quickbooks_types::Attachable;
#[cfg(feature = "builder")]
{
use quickbooks_types::AttachableBuilder;
// AttachableBuilder::file(...) sets file_path, derives file_name and content_type from extension
let attachable = Attachable::new()
.note("Invoice backup")
// .file(&std::path::Path::new("docs/invoice.pdf"))?
.build();
assert!(attachable.is_ok());
}The reports module provides:
- Richly-typed report models:
reports::models::{Report, Row, ColData, ...} - Strongly-typed parameter builders per report:
reports::types::<Report>Params - Common enums and ID wrappers for parameters:
reports::params::*
Build a query string for a report:
use chrono::NaiveDate;
use quickbooks_types::reports::types::*;
use quickbooks_types::reports::params::*;
let balance_sheet = BalanceSheetParams::new()
.accounting_method(AccountingMethod::Cash)
.start_date(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap())
.end_date(NaiveDate::from_ymd_opt(2024, 12, 31).unwrap())
.date_macro(DateMacro::ThisFiscalYear)
.summarize_column_by(SummarizeColumnBy::Month);
println!("{}", balance_sheet.to_query_string());
// -> accounting_method=Cash&start_date=2024-01-01&end_date=2024-12-31&date_macro=This Fiscal Year&summarize_column_by=MonthAnother example:
use chrono::NaiveDate;
use quickbooks_types::reports::types::*;
use quickbooks_types::reports::params::*;
let ap_aging = APAgingDetailParams::new()
.as_of_date(NaiveDate::from_ymd_opt(2024, 6, 30).unwrap())
.aging_method(AgingMethod::Current)
.vendor(VendorId(789))
.column("Name")
.column("DueDate")
.column("Amount");
println!("{}", ap_aging.to_query_string());Parsing a report result:
use quickbooks_types::reports::models::Report;
let json = r#"{
"Header": { "ReportName": "BalanceSheet" },
"Columns": { "Column": [ { "ColTitle": "Total", "ColType": "Money" } ] },
"Rows": { "Row": [] }
}"#;
let report: Report = serde_json::from_str(json).unwrap();
assert_eq!(report.name(), Some("BalanceSheet"));Polars integration (feature = "polars"):
- Enables
reports::polarshelpers andreports::QBPolarsError - Provide your own conversion to Polars DataFrames depending on your use case
Top-level entities for which QBItem is implemented and a Display impl is provided:
- Account, Attachable, Bill, BillPayment, CompanyInfo, Customer, Employee, Estimate, Invoice, Item, Payment, Preferences, SalesReceipt, Vendor
Supporting value types (non-exhaustive):
common:NtRef,MetaData,Addr,Email,PhoneNumber,WebAddr,TxnTaxDetail,LinkedTxn, and othersline:Line,LineDetailand its variants (e.g.,SalesItemLineDetail,SubTotalLineDetail, etc.),LineField(alias forVec<Line>)
Operation traits (selected):
QBCreatable:can_create(&self) -> bool– entity meets required fields for creationQBReadable:can_read(&self) -> bool– true if ID is presentQBDeletable:can_delete(&self) -> bool– default requires both ID and sync_tokenQBFullUpdatable:can_full_update(&self) -> bool– type-specific requirementsQBSparseUpdateable:can_sparse_update(&self) -> bool– typicallycan_full_update()+sparse == trueQBVoidable:can_void(&self) -> bool– default requires both ID and sync_tokenQBSendable/QBPDFable: marker traits for entities that can be emailed / retrieved as PDF in QBOQBToRef:to_ref(&self) -> Result<NtRef, QBTypeError>– convert to reference usable in other entities
Note: These methods validate local preconditions only; they do not contact QBO.
use quickbooks_types::QBTypeError;
#[derive(Debug, thiserror::Error)]
pub enum QBTypeError {
#[cfg(feature = "builder")]
#[error("Error validating QB Object in builder: {0}")]
ValidationError(String),
#[error("Missing field in QB Object: {0}")]
MissingField(&'static str),
#[error("QB Item could not be referenced!")]
QBToRefError,
}- IDs and
sync_tokenare required for delete and void operations (has_read()check) - Builders (feature = "builder") return
Result<_, QBTypeError>onbuild() - Some enums contain placeholder or minimal variants where the QBO surface is large; open an issue or PR to extend as needed
Issues and PRs are welcome. If you need additional entities, fields, or extended report handling, feel free to propose a change.
API documentation is available at docs.rs/quickbooks-types.
MIT. See the LICENSE file for details.