Skip to main content

Acumatica REST API Cookbook

Accumulated patterns, quirks, and solutions from production Acumatica integrations.

Authentication

Session-Based Auth

POST /entity/auth/login
Content-Type: application/json

{
"name": "api-bot",
"password": "...",
"company": "TenantName"
}

Returns HTTP 204 on success (not 200). Extract Set-Cookie headers for the session.

info

Session cookies expire after 20 minutes. Refresh proactively in long-running workers.

Concurrent Session Limit

Acumatica licenses limit concurrent API sessions (~2-3). Use a session gate pattern:

  • Redis sorted set tracks active sessions
  • Each service acquires a slot before authenticating
  • Slots released on logout or TTL expiry
  • Graceful degradation: local semaphore if Redis is unavailable

Entity Operations

PUT for Create AND Update

Acumatica uses PUT for both create and update (upsert pattern). POST to entity endpoints returns HTTP 406 (Not Acceptable).

# Correct: PUT for both create and update
PUT /entity/default/24.200.001/Customer

# Wrong: POST returns 406
POST /entity/default/24.200.001/Customer

Value Wrapper Pattern

All field values are wrapped in {value: x} objects:

{
"CustomerName": {"value": "ACME Corp"},
"Status": {"value": "Active"},
"CreditLimit": {"value": 50000}
}

Read values by unwrapping: record.CustomerName.value

Schema Endpoint

GET /entity/default/24.200.001/{Entity}/$adHocSchema

Returns the full field template including custom fields with type metadata. This is the definitive way to verify custom fields exist after a customization publish.

OData Query Patterns

Basic Query

GET /entity/default/24.200.001/Customer?$top=10&$filter=Status eq 'Active'

Expanding Sub-Entities

GET /entity/default/24.200.001/Customer/C000004?$expand=MainContact,CreditVerificationRules,Salespersons
warning

$expand works on individual record GETs but may return empty on list queries. Some sub-entities (CreditVerificationRules, Attributes) are unreliable in list context.

Nested Expand Not Supported

# Wrong: nested $expand syntax
$expand=WarehouseDetails($select=WarehouseID)

# Correct: simple $expand
$expand=WarehouseDetails

Filtering Limitations

  • Custom attributes (e.g., AttributeWAYFAIRCON) cannot be used in $filter — throws KeyNotFoundException
  • $select=custom causes 500 errors — use $adHocSchema to inspect custom fields
  • The note field is auto-included in responses but not a filterable property

Custom Fields

Custom Fields vs Attributes

FeatureCustom Fields (DAC UDF)Attributes
Created viaCustomization project (C# code)CS205000 (UI, no code)
Appears incustom.{ViewName}.{FieldName}Attributes[] array
QueryableIn $adHocSchemaWith $expand=Attributes on individual GETs
List queriesMay show in custom sectionEmpty on list queries
Best forBusiness logic, computed fieldsSimple data storage, dedup keys

Writing Attributes

PUT /entity/default/24.200.001/StockItem/00004
{
"Attributes": [
{
"AttributeID": {"value": "HUBSPOTPID"},
"Value": {"value": "12345678"}
}
]
}

Entity Name Gotchas

Expected NameActual API NameNotes
InventoryItemStockItem404 if you use InventoryItem
InventoryAllocationDetailN/AInquiry entity — not in REST API
AttributeN/ANot exposed — use UI (CS205000)

Common Error Patterns

ErrorCauseFix
HTTP 406Using POST for entity CRUDUse PUT
HTTP 401Session expiredRe-authenticate
HTTP 500 with $select=customKnown Acumatica bugUse $adHocSchema instead
KeyNotFoundException on filterFiltering by custom attributeUse date-based or standard field filters
Account lockedToo many concurrent sessionsWait 15 min or unlock in SM201010