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.

1

Initialize the Dynamic Client

Create an AcumaticaClient instance that automatically discovers your API structure

python
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

python
# 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

python
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

python
# 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

python
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

python
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

python
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

python
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

python
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

python
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.")