5 minute setup
Quick Start Guide
Get up and running with Easy-Acumatica v0.4.x in minutes.
Experience the power of dynamic API generation.
Prerequisites
- Python 3.7 or higher installed
- Acumatica instance with API access enabled
- API credentials (username, password, tenant, branch)
- Easy-Acumatica v0.4.x installed (
pip install easy-acumatica
)
1
Initialize the Dynamic Client
Create an AcumaticaClient instance that automatically discovers your API structure
from easy_acumatica import AcumaticaClient
# Initialize the client - it discovers everything automatically!
client = AcumaticaClient(
base_url="https://your-instance.acumatica.com",
username="your_username",
password="your_password",
tenant="YourTenant",
branch="YourBranch"
)
# That's it! Your client is ready with all services and models
What's Happening?
When you initialize the client, it automatically:
- Discovers all available endpoints
- Generates models for every entity
- Creates service methods dynamically
- Includes your custom fields
2
Explore Dynamic Services
Services are automatically attached to your client based on available endpoints
# See what services were dynamically created
available_services = [
attr for attr in dir(client)
if not attr.startswith('_') and hasattr(getattr(client, attr), 'get_list')
]
print(f"Found {len(available_services)} services:", available_services)
# Check available models
available_models = [
name for name in dir(client.models)
if not name.startswith('_')
]
print(f"Generated {len(available_models)} models:", available_models[:10], "...")
Common Service Operations
from easy_acumatica import QueryOptions, F
# Get all customers
customers = client.customers.get_list()
# Get a specific customer by ID
customer = client.customers.get_by_id("CUST001")
# Get customer by key fields
customer = client.customers.get_by_keys(CustomerID="ABCCOMP")
# Query customers with QueryOptions
options = QueryOptions(
filter=F.Status == "Active",
select=["CustomerID", "CustomerName", "Email"],
top=50
)
active_customers = client.customers.get_list(options=options)
# Create a new customer
new_customer = client.models.Customer(
CustomerID="NEWCUST01",
CustomerName="New Customer Inc.",
Email="contact@newcustomer.com",
Status="Active"
)
result = client.customers.put_entity(new_customer)
# Delete a customer
client.customers.delete_by_id("OLDCUST01")
Pro Tips
- Service names match your endpoint names (pluralized)
- All CRUD operations are available automatically
- Custom actions from your instance are included
- Type hints provide full IDE support
Available Methods
get_list(**params)
get_by_id(id)
get_by_keys(**keys)
put_entity(entity)
delete_by_id(id)
invoke_action_*()
3
Work with Dynamic Models
Models are generated from your instance schema with full type safety
# Models are dynamically generated with all your fields
new_customer = client.models.Customer(
CustomerID="CUST001",
CustomerName="Acme Corporation",
Email="contact@acmecorp.com",
Phone="555-0123",
# Address fields
AddressLine1="123 Main Street",
City="New York",
State="NY",
PostalCode="10001",
# Your custom fields are here too!
UsrCustomField="Value" # If it exists in your instance
)
# Create the customer
result = client.customers.put_entity(new_customer)
print(f"Created customer: {result.CustomerID}")
Model Features
- Type-safe field access
- Validation built-in
- Custom fields included
- IDE autocomplete
4
Query with OData
Use powerful OData query wrappers for filtering, sorting, and pagination
from easy_acumatica import QueryOptions, F, CustomField
# F is a factory for creating filter expressions
# Use it to build complex, type-safe filters
# Simple filter
filter1 = F.Status == "Active"
# Complex filter with logical operators
filter2 = (F.Amount > 1000) & (F.Status == "Active") | (F.Priority == 1)
# String functions
filter3 = F.CustomerName.startswith("ABC") & F.Email.contains("@company.com")
# Date functions
filter4 = F.CreatedDate.year() == 2024
# Custom fields
custom_field = CustomField.field("ItemSettings", "UsrRepairItemType", "InventoryItem")
options = QueryOptions(
filter=F.Status == "Active",
custom=[custom_field],
expand=["InventoryItem"] # Automatically added
)
Filtering
Build complex filters with the F factory
from easy_acumatica import QueryOptions, F
# Simple equality
options = QueryOptions(filter=F.State == "CA")
# Multiple conditions with logical operators
options = QueryOptions(
filter=(F.CustomerID == "ABC") & (F.Amount > 1000) & (F.Status != "Cancelled")
)
# String functions
options = QueryOptions(
filter=F.CustomerName.tolower().startswith("acme") & F.Email.endswith("@corp.com")
)
# In operator (v4)
options = QueryOptions(
filter=F.Status.in_(["Active", "Pending", "Processing"])
)
Selection & Expansion
Control what fields and related data to retrieve
from easy_acumatica import QueryOptions
# Select specific fields only
options = QueryOptions(
select=["CustomerID", "CustomerName", "Email", "Phone"]
)
# Expand related entities
options = QueryOptions(
expand=["Details", "Customer", "ShippingAddress"]
)
# Combine select and expand
options = QueryOptions(
select=["OrderNbr", "Date", "Total"],
expand=["Details", "Customer"],
filter=F.Status == "Open"
)
Sorting & Pagination
Order results and implement paging
from easy_acumatica import QueryOptions
# Sort by single field
options = QueryOptions(orderby="Date desc")
# Sort by multiple fields
options = QueryOptions(orderby=["Priority asc", "Date desc"])
# Pagination
page_size = 20
page = 3
options = QueryOptions(
top=page_size,
skip=(page - 1) * page_size,
orderby="CustomerName"
)
Custom Fields
Include custom fields in your queries
from easy_acumatica import QueryOptions, CustomField
# Define custom fields
repair_type = CustomField.field("ItemSettings", "UsrRepairItemType", "InventoryItem")
custom_attr = CustomField.attribute("Document", "OPERATSYST")
# Use in query options
options = QueryOptions(
filter=F.Status == "Active",
custom=[repair_type, custom_attr],
select=["InventoryID", "Description"]
)
# The expand parameter is automatically updated to include "InventoryItem"
Complete Example
Putting it all together - a real-world integration
from easy_acumatica import AcumaticaClient, QueryOptions, F
from datetime import datetime, timedelta
# Initialize client
client = AcumaticaClient(
base_url="https://your-instance.acumatica.com",
username="api_user",
password="secure_password",
tenant="Company",
branch="MAIN"
)
def process_monthly_orders():
"""Process orders from the last month and create invoices"""
# Calculate date range
end_date = datetime.now()
start_date = end_date - timedelta(days=30)
# Build query options for completed orders
order_options = QueryOptions(
filter=(F.Status == "Completed") & (F.Date >= start_date),
expand=["Details", "Customer"],
orderby=["Date desc"]
)
# Get completed orders
completed_orders = client.sales_orders.get_list(options=order_options)
print(f"Found {len(completed_orders)} completed orders")
# Process each order
for order in completed_orders:
try:
# Check if invoice already exists
invoice_options = QueryOptions(
filter=(F.CustomerID == order.CustomerID) &
(F.Description == f"Order {order.OrderNbr}")
)
existing_invoices = client.invoices.get_list(options=invoice_options)
if existing_invoices:
print(f"Invoice already exists for order {order.OrderNbr}")
continue
# Create invoice from order
invoice = client.models.Invoice(
CustomerID=order.CustomerID,
Date=datetime.now().strftime('%Y-%m-%d'),
Description=f"Invoice for Order {order.OrderNbr}",
Details=[
client.models.InvoiceDetail(
InventoryID=detail.InventoryID,
Quantity=detail.Quantity,
UnitPrice=detail.UnitPrice,
DiscountPercent=detail.DiscountPercent
)
for detail in order.Details
]
)
# Create the invoice
created_invoice = client.invoices.put_entity(invoice)
print(f"Created invoice {created_invoice.RefNbr} for order {order.OrderNbr}")
# Optional: Release the invoice if action is available
if hasattr(client.invoices, 'invoke_action_release'):
client.invoices.invoke_action_release(entity=created_invoice)
print(f"Released invoice {created_invoice.RefNbr}")
except Exception as e:
print(f"Error processing order {order.OrderNbr}: {str(e)}")
continue
return completed_orders
# Run the process
if __name__ == "__main__":
orders = process_monthly_orders()
print(f"Processing complete. Processed {len(orders)} orders.")