---
# === IDENTITY ===
id: business/erp-integration/acumatica-screen-based-api/2026
canonical_question: "How does the Acumatica screen-based API work and when should you use it vs REST?"
aliases:
  - "Acumatica screen-based SOAP API vs contract-based REST API differences"
  - "When to use Acumatica screen-based web services vs REST endpoint"
  - "Acumatica PX.Soap.dll screen-based API wrapper guide"
  - "Migrating from Acumatica screen-based API to contract-based REST API"
entity_type: erp_integration
domain: business > erp-integration > acumatica-screen-based-api
region: global
jurisdiction: global
temporal_scope: 2020-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Acumatica ERP"
    vendor: "Acumatica"
    version: "2024 R2 (24.200)"
    edition: "All editions (Small Business, Standard, Enterprise)"
    deployment: "cloud"
    api_surface: "SOAP (Screen-Based), REST (Contract-Based), OData"

# === VERIFICATION ===
last_verified: 2026-03-02
confidence: 0.88
version: 1.0
first_published: 2026-03-02

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: volatile
  last_breaking_change: "2023 R2 - Contract-based SOAP endpoints (17.200, 18.200) removed; screen-based SOAP endpoints retained"
  next_review: 2026-08-29
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Screen-based API is tightly coupled to UI forms - any screen layout change (moving a control, adding a border) can break existing integrations"
  - "Contract-based SOAP API endpoints (17.200, 18.200) were removed in 2023 R2 - only REST and screen-based SOAP remain"
  - "API user sessions are limited by license - exceeding the Maximum Web Services API Users limit returns an error and blocks login"
  - "Rate limiting enforced per-minute - when requests reach 50% of the licensed limit, subsequent requests are delayed (throttled)"
  - "Screen-based API requires .NET (C#) client - PX.Soap.dll wrapper only supports .NET environments"
  - "No JSON support on screen-based API - SOAP/XML only, making it heavier than REST for modern integrations"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User only needs standard CRUD operations on business objects"
    use_instead: "business/erp-integration/acumatica-rest-api/2026"
  - condition: "User needs to connect Power BI or Excel to Acumatica data"
    use_instead: "business/erp-integration/acumatica-odata/2026"
  - condition: "User is building a new integration from scratch with no legacy constraints"
    use_instead: "business/erp-integration/acumatica-rest-api/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: integration_pattern
    question: "What integration pattern do you need?"
    type: choice
    options:
      - "real-time sync (individual records, <1s latency)"
      - "batch/bulk (scheduled, high volume)"
      - "event-driven (webhook, push notifications)"
      - "automation of specific screen actions"
  - key: data_volume
    question: "What's your daily data volume?"
    type: choice
    options:
      - "< 1,000 records/day"
      - "1,000-100,000 records/day"
      - "> 100,000 records/day"
  - key: direction
    question: "What's the data flow direction?"
    type: choice
    options:
      - "inbound (writing to Acumatica)"
      - "outbound (reading from Acumatica)"
      - "bidirectional sync"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/acumatica-screen-based-api/2026"
suggested_citation: "Source: knowledgelib.io - AI Knowledge Library (verified 2026-03-02)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "business/erp-integration/acumatica-rest-api/2026"
      label: "Acumatica contract-based REST API capabilities and endpoints"
  solves: []
  alternative_to:
    - id: "business/erp-integration/acumatica-rest-api/2026"
      label: "Acumatica REST API (preferred for new integrations)"
  often_confused_with:
    - id: "business/erp-integration/acumatica-rest-api/2026"
      label: "Contract-based REST API - different architecture, not screen-bound"

# === SOURCES ===
sources:
  - id: src1
    title: "Yes, We Have an API for That! An Introduction to the Acumatica Cloud ERP APIs"
    author: Acumatica
    url: https://www.acumatica.com/blog/yes-we-have-an-api-for-that-an-introduction-to-the-acumatica-cloud-erp-apis/
    type: official_docs
    published: 2023-06-15
    reliability: authoritative
  - id: src2
    title: "23r2 - Support for SOAP Based API / WSDL Ends"
    author: Acumatica Community
    url: https://community.acumatica.com/develop-integrations-with-web-services-apis-289/23r2-support-for-soap-based-api-wsdl-ends-17047
    type: community_resource
    published: 2023-08-01
    reliability: high
  - id: src3
    title: "Unlocking Acumatica Web Services: REST API, OData, and Integration Best Practices"
    author: Acumatica
    url: https://www.acumatica.com/blog/acumatica-web-services-rest-api-odata-and-integration-best-practices/
    type: official_docs
    published: 2024-11-15
    reliability: authoritative
  - id: src4
    title: "Acumatica ERP Integration Development Guide (2020 R2)"
    author: Acumatica
    url: https://www.acumatica.com/media/2020/09/AcumaticaERP_IntegrationDevelopmentGuide.pdf
    type: official_docs
    published: 2020-09-18
    reliability: authoritative
  - id: src5
    title: "Acumatica API Guide: How to Get Started"
    author: Tipalti
    url: https://tipalti.com/blog/acumatica-api/
    type: technical_blog
    published: 2024-06-10
    reliability: moderate_high
  - id: src6
    title: "License Restrictions for API Users"
    author: Acumatica
    url: https://help.acumatica.com/(W(35))/Wiki/ShowWiki.aspx?pageid=7a796856-3dec-4a4f-abf8-171324c9642b
    type: official_docs
    published: 2024-01-15
    reliability: authoritative
  - id: src7
    title: "Configuring the Contract-Based REST API"
    author: Acumatica
    url: https://help.acumatica.com/(W(3))/Wiki/ShowWiki.aspx?pageid=91dda8ed-5e92-48a5-a176-9a255506d0d6
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
---

# Acumatica Screen-Based API: How It Works and When to Use It vs REST

## TL;DR

- **Bottom line**: The Acumatica screen-based API is a SOAP/XML web service that maps directly to ERP form elements, giving access to every screen action and field. Use the contract-based REST API for new integrations; use screen-based only when you need functionality not yet exposed through the contract-based API. [src1]
- **Key limit**: Screen-based API is tightly coupled to UI layouts -- any screen customization (moving a control, changing a form group) can break your integration code and require recompilation. [src1, src5]
- **Watch out for**: Contract-based SOAP endpoints (versions 17.200 and 18.200) were removed in Acumatica 2023 R2, but screen-based SOAP endpoints remain available. Do not confuse the two -- they are different APIs with different deprecation timelines. [src2]
- **Best for**: Automating screen-specific actions (report generation, processing screens, custom actions) not exposed through the REST API, and maintaining legacy integrations built before contract-based APIs existed. [src1, src4]
- **Authentication**: OAuth 2.0 (authorization code or resource owner password credentials) or cookie-based session authentication via Login/Logout SOAP methods. [src3, src7]

## System Profile

This card covers Acumatica ERP's screen-based SOAP web services API and compares it with the contract-based REST API. The screen-based API has been available since Acumatica's earliest versions and provides direct programmatic access to every form in the system. The contract-based REST API was introduced in Acumatica 5.3 (2016) as a more stable, decoupled alternative. Both APIs are available in all Acumatica editions (Small Business, Standard, Enterprise) across cloud, hosted, and on-premise deployments. [src1, src4]

This card does NOT cover OData-based data retrieval (Generic Inquiry-based or DAC-based), which is a separate read-only data access mechanism primarily used for BI tools like Power BI and Excel. [src3]

| Property | Value |
|---|---|
| **Vendor** | Acumatica |
| **System** | Acumatica ERP 2024 R2 (24.200) |
| **API Surface** | SOAP (Screen-Based) + REST (Contract-Based) |
| **Current API Version** | Screen-Based: per-screen WSDL; REST: 24.200.001 |
| **Editions Covered** | Small Business, Standard, Enterprise |
| **Deployment** | Cloud / Hosted / On-Premise |
| **API Docs URL** | [Acumatica Integration Development Guide](https://www.acumatica.com/media/2020/09/AcumaticaERP_IntegrationDevelopmentGuide.pdf) |
| **Status** | Screen-Based: Maintenance (supported, not recommended for new dev); REST: GA (actively developed) |

## API Surfaces & Capabilities

Acumatica provides three distinct API surfaces, each with different strengths and trade-offs. The screen-based API offers the broadest functional coverage but the least stability; the contract-based REST API offers stability and ease of use but may not expose every screen action. [src1, src3]

| API Surface | Protocol | Best For | Stability | Coverage | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| Screen-Based SOAP | HTTPS/XML (SOAP) | Automating any screen action, processing screens, legacy integrations | Low - breaks on UI changes | Complete (every form) | Yes | Via Export/Import methods |
| Contract-Based REST | HTTPS/JSON (REST) | CRUD operations, new integrations, cross-platform clients | High - decoupled from UI | Partial (configured endpoints only) | Yes | Limited (batch via $expand) |
| Contract-Based SOAP | HTTPS/XML (SOAP) | Legacy contract-based integrations | High - decoupled from UI | Same as REST | Yes | Limited |
| OData (GI-Based) | HTTPS/JSON (OData v4) | BI tools, reporting, read-only data access | High | Generic Inquiries only | Yes | Read-only |
| OData (DAC-Based) | HTTPS/JSON (OData v4) | Direct DAC access for reporting | High | DAC-exposed entities | Yes | Read-only |

[src1, src3]

## Rate Limits & Quotas

### Per-Request Limits

| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max concurrent API user sessions | License-dependent | All API surfaces | Configured on SM604000 (License Monitoring Console); exceeding returns login error [src6] |
| Request body size | No published hard limit | REST API | Denial Code 511 returned for oversized payloads |
| Export batch size | Configurable per call | Screen-Based API Export() | Set via the TopCount parameter in Export() calls [src4] |
| Composite batch size | 1,000 per $batch request | REST API | Each subrequest counts as a separate API call [src3] |

[src3, src6]

### Rolling / Daily Limits

| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| API requests per minute | License-dependent | Per minute | At 50% of limit, requests are throttled (delayed); at 100%, requests are rejected [src6] |
| Concurrent API users | License-dependent | Concurrent sessions | Small Business: fewer; Enterprise: more. Check SM604000 for exact limit [src6] |
| Total API calls | No published daily cap | 24h | Governed by per-minute rate limit and concurrent user limit [src6] |

[src6]

## Authentication

Acumatica supports multiple authentication methods across its API surfaces. OAuth 2.0 is recommended for all new integrations. The screen-based API historically used cookie-based authentication via Login/Logout SOAP methods, but OAuth 2.0 tokens can also be used. [src3, src7]

| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 Authorization Code | Interactive applications, user-context operations | Configurable | Yes | Recommended for web apps. Register on SM303010 (Connected Applications). [src3] |
| OAuth 2.0 Resource Owner Password | Server-to-server integrations, legacy migration | Configurable | Yes | Simpler setup but less secure than auth code flow. [src3] |
| Cookie-based (Login/Logout SOAP) | Legacy screen-based API integrations | Session-based | No - re-login required | Uses Login() method with username, password, company, branch. Logout() to release session. [src4] |
| OAuth 2.0 Client Credentials | Service-to-service with no user context | Configurable | Yes | Available in newer Acumatica versions. [src3] |

[src3, src4, src7]

### Authentication Gotchas

- **Screen-based Login() counts against API user limit**: Each Login() call consumes an API user session slot. If you forget to call Logout(), the session persists until timeout, potentially exhausting your licensed API user count. [src4, src6]
- **OAuth tokens work for both API surfaces**: An OAuth 2.0 access token obtained for the contract-based REST API can also be used with screen-based SOAP calls by passing it in the Authorization header. You do not need separate authentication. [src3]
- **ODBC connectivity was removed in 2021 R2**: Do not attempt to use ODBC for data access. All data access must go through APIs or OData. [src5]

## Constraints

- **Screen-based API is UI-coupled**: Any change to a form's layout -- moving a field between groups, adding/removing a tab, renaming a control -- changes the WSDL and can break compiled client code. This is the fundamental architectural difference from the contract-based API. [src1, src5]
- **PX.Soap.dll wrapper requires .NET**: The screen-based API wrapper (PX.Soap.dll) only works in .NET environments. Non-.NET clients must work directly with raw SOAP XML, which is significantly more complex. [src4]
- **Contract-based SOAP endpoints removed in 2023 R2**: The 17.200 and 18.200 contract-based SOAP endpoints were removed. Screen-based SOAP endpoints remain. Do not confuse these two -- "SOAP" is not a single API in Acumatica. [src2]
- **Screen-based API not officially recommended for new development**: Acumatica explicitly recommends contract-based REST API for all new integrations. Screen-based API is in maintenance mode. [src1, src5]
- **Not all screen actions are exposed in REST API**: Some processing screens, custom actions, and advanced form operations are only accessible through the screen-based API. This is the primary reason the screen-based API still exists. [src1, src4]
- **API user sessions are license-limited**: The number of concurrent API sessions is capped by your Acumatica license. Exceeding this limit blocks new API logins entirely. Check SM604000 for your limit. [src6]

## Integration Pattern Decision Tree

```
START - Need to integrate with Acumatica ERP
|-- Is this a new integration or maintaining an existing one?
|   |-- NEW integration
|   |   |-- Do you need to automate a screen action not exposed via REST?
|   |   |   |-- YES (e.g., specific processing screen, custom action button)
|   |   |   |   --> Screen-Based SOAP API (only option for these operations) [src1, src4]
|   |   |   |-- NO (standard CRUD, business object operations)
|   |   |       --> Contract-Based REST API (recommended) [src1, src3]
|   |   |-- Do you need read-only data for BI/reporting?
|   |   |   |-- YES --> OData (GI-based or DAC-based) [src3]
|   |   |   |-- NO --> REST API
|   |   |-- What client environment?
|   |       |-- .NET (C#) --> REST API or Screen-Based with PX.Soap.dll wrapper [src4]
|   |       |-- Non-.NET (Python, JavaScript, Java) --> REST API (no screen-based wrapper) [src3]
|   |-- EXISTING screen-based integration
|       |-- Is it working and stable?
|       |   |-- YES --> Keep it, but plan migration to REST API over time [src1]
|       |   |-- NO (breaking on upgrades) --> Migrate to REST API now [src1, src5]
|       |-- Can all operations be replicated with REST API?
|           |-- YES --> Migrate to REST API [src1, src7]
|           |-- NO (screen-specific actions needed)
|               --> Keep screen-based for those operations, use REST for everything else [src1]
|-- What's the data flow direction?
|   |-- Read/Export data from Acumatica
|   |   |-- Small volume, specific records --> REST API GET [src3]
|   |   |-- Bulk export --> Screen-Based Export() or OData [src4]
|   |-- Write/Import data to Acumatica
|   |   |-- Individual records --> REST API PUT/POST [src3]
|   |   |-- Bulk import --> Screen-Based Import() or REST API batch [src4]
|   |-- React to changes in Acumatica
|       --> Push Notifications (SM302000) or Webhooks (SM304000) [src3]
|-- Error handling strategy?
    |-- Zero-loss required --> Implement idempotency + GetProcessStatus() polling [src4]
    |-- Best-effort --> REST API with retry on 429/500 [src3]
```

## Quick Reference

| Operation | Screen-Based API | Contract-Based REST API | Notes |
|---|---|---|---|
| **Endpoint URL** | `{site}/Soap/{FormID}.asmx` | `{site}/entity/{EndpointName}/{Version}/{EntityName}` | Screen-based uses form IDs (e.g., AR301000.asmx) [src4] |
| **WSDL** | `{site}/Soap/{FormID}.asmx?WSDL` | N/A (OpenAPI/Swagger via SM207000) | Screen-based generates WSDL per form [src4] |
| **Create record** | Submit() with Content object | `PUT /entity/Default/24.200.001/{Entity}` | REST uses JSON; screen-based uses SOAP XML [src3, src4] |
| **Read records** | Export() with filters | `GET /entity/Default/24.200.001/{Entity}?$filter=...` | REST supports OData query syntax [src3, src4] |
| **Update record** | Submit() with modified Content | `PUT /entity/Default/24.200.001/{Entity}` | Both use record key fields for identification [src3, src4] |
| **Delete record** | Clear() then Submit() | `DELETE /entity/Default/24.200.001/{Entity}/{keys}` | Screen-based requires clearing then submitting [src4] |
| **Execute action** | Submit() with action trigger | `POST /entity/Default/24.200.001/{Entity}/{Action}` | Screen-based can trigger any button; REST only configured actions [src3, src4] |
| **Check async status** | GetProcessStatus() | `GET /entity/Default/24.200.001/{Entity}?$longRunning=true` | Screen-based has dedicated polling method [src4] |
| **File attachment** | Via Submit() with file fields | `PUT /entity/Default/24.200.001/{Entity}/{keys}/files/{filename}` | REST has cleaner file handling [src3] |
| **Login** | Login(name, password, company, branch) | OAuth 2.0 token in Authorization header | Screen-based: session cookie; REST: Bearer token [src3, src4] |
| **Logout** | Logout() | N/A (token expiry) | Screen-based MUST call Logout() to free session [src4, src6] |
| **Schema discovery** | GetSchema() / SetSchema() | `/entity/Default/24.200.001` (list entities) | Screen-based caches schema locally via PX.Soap.dll [src4] |

## Step-by-Step Integration Guide

### 1. Determine which API surface to use

Evaluate whether the integration requires screen-specific functionality. If the operation can be performed through the REST API's configured endpoints, use REST. Only fall back to screen-based API when you need access to processing screens, custom actions, or form-specific logic not exposed through contract-based endpoints. [src1]

```plaintext
Decision checklist:
- [ ] Can the operation be done via REST API endpoint? --> Use REST
- [ ] Does it require a specific screen action (e.g., Release, Process)? --> Check if action is configured in REST endpoint first
- [ ] Is the client environment .NET? --> Screen-based option available
- [ ] Is the client non-.NET (Python, JS)? --> Must use REST API
- [ ] Is this a greenfield integration? --> Use REST API
```

**Verify**: Check the REST API endpoint configuration on SM207000 to see if your required entities and actions are exposed.

### 2. Set up authentication (REST API - recommended path)

Register your application as a connected application on SM303010 (Connected Applications) for OAuth 2.0. For server-to-server integrations, use the Resource Owner Password Credentials flow or Client Credentials flow. [src3, src7]

```bash
# Input:  Acumatica instance URL, client_id, client_secret, username, password
# Output: OAuth 2.0 access token

# Step 1: Obtain access token (Resource Owner Password flow)
curl -X POST "https://your-instance.acumatica.com/identity/connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "username=admin" \
  -d "password=YOUR_PASSWORD" \
  -d "scope=api"

# Expected response:
# {
#   "access_token": "eyJhbGciOiJSUzI1...",
#   "token_type": "Bearer",
#   "expires_in": 3600
# }
```

**Verify**: Use the access token to call the REST API and confirm authentication works: `GET /entity/Default/24.200.001/` should return a list of available entities.

### 3. Set up authentication (Screen-Based API - legacy path)

For screen-based SOAP integrations, use the Login() method via the PX.Soap.dll wrapper or raw SOAP. The wrapper simplifies schema management. [src4]

```csharp
// Input:  Acumatica URL, username, password, company name
// Output: Authenticated SOAP client session

// Add reference to PX.Soap.dll from ScreenBasedAPIWrapper folder
using PX.Soap;

string url = "https://your-instance.acumatica.com";
string username = "admin";
string password = "YOUR_PASSWORD";
string company = "MyCompany";

// Create SOAP client for a specific screen (e.g., Sales Order SO301000)
var soapClient = new SO301000Screen();
soapClient.Url = url + "/Soap/SO301000.asmx";
soapClient.CookieContainer = new System.Net.CookieContainer();

// Login - this consumes an API user session slot
soapClient.Login(username, password, company, null, null);

// IMPORTANT: Always call Logout() when done to release the session
// soapClient.Logout();
```

**Verify**: A successful Login() call returns without error. An API user limit error means your licensed API session count is exceeded -- check SM604000.

### 4. Perform CRUD operations via REST API

Use standard REST methods for creating, reading, updating, and deleting records. [src3, src7]

```bash
# Input:  OAuth 2.0 access token, Acumatica instance URL
# Output: CRUD operations on Stock Items

# Read stock items with filter
curl -X GET "https://your-instance.acumatica.com/entity/Default/24.200.001/StockItem?\$filter=InventoryID eq 'AALEGO500'" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json"

# Create a new stock item
curl -X PUT "https://your-instance.acumatica.com/entity/Default/24.200.001/StockItem" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "InventoryID": {"value": "NEWITEM001"},
    "Description": {"value": "New Test Item"},
    "ItemClass": {"value": "STOCKITEM"}
  }'
```

**Verify**: `GET /entity/Default/24.200.001/StockItem?$filter=InventoryID eq 'NEWITEM001'` returns the created record.

### 5. Perform operations via Screen-Based API (when REST is insufficient)

Use the screen-based API for operations that require specific screen actions not exposed through REST endpoints. [src4]

```csharp
// Input:  Authenticated SOAP client, sales order data
// Output: Sales order created and released in Acumatica

// Get the schema for the Sales Orders screen
var schema = PX.Soap.Helper.GetSchema<SO301000Content>(soapClient);

// Set field values on the form
var commands = new SO301000Command[]
{
    // Navigate to a new record
    schema.Actions.Insert,
    // Set order type
    new SO301000Value { Value = "SO", LinkedCommand = schema.OrderSummary.OrderType },
    // Set customer
    new SO301000Value { Value = "ABARTENDE", LinkedCommand = schema.OrderSummary.CustomerID },
    // Set description
    new SO301000Value { Value = "API-created order", LinkedCommand = schema.OrderSummary.Description },
    // Save the record
    schema.Actions.Save
};

// Submit executes the commands sequentially on the screen
var result = soapClient.Submit(commands);

// IMPORTANT: Always logout when done
soapClient.Logout();
```

**Verify**: Log into Acumatica UI, navigate to Sales Orders (SO301000), and confirm the new order appears.

## Code Examples

### Python: REST API CRUD Operations

```python
# Input:  Acumatica instance URL, OAuth credentials
# Output: Stock item created, queried, and updated

import requests

base_url = "https://your-instance.acumatica.com"
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"

# Authenticate via OAuth 2.0
token_resp = requests.post(
    f"{base_url}/identity/connect/token",
    data={
        "grant_type": "password",
        "client_id": client_id,
        "client_secret": client_secret,
        "username": "admin",
        "password": "YOUR_PASSWORD",
        "scope": "api"
    }
)
token = token_resp.json()["access_token"]
headers = {
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json"
}

# Create a stock item (PUT for upsert)
item = {
    "InventoryID": {"value": "PYITEM001"},
    "Description": {"value": "Python-created item"},
    "ItemClass": {"value": "STOCKITEM"}
}
resp = requests.put(
    f"{base_url}/entity/Default/24.200.001/StockItem",
    headers=headers, json=item
)
print(f"Create: {resp.status_code}")

# Query with filter
resp = requests.get(
    f"{base_url}/entity/Default/24.200.001/StockItem",
    headers=headers,
    params={"$filter": "InventoryID eq 'PYITEM001'"}
)
print(f"Query: {resp.json()}")
```

### C#: Screen-Based API Export with PX.Soap.dll

```csharp
// Input:  Authenticated screen-based SOAP client
// Output: Exported stock items from Inventory screen

// Reference PX.Soap.dll from Acumatica installation
using PX.Soap;

var client = new IN202500Screen();
client.Url = "https://your-instance.acumatica.com/Soap/IN202500.asmx";
client.CookieContainer = new System.Net.CookieContainer();
client.Login("admin", "password", "MyCompany", null, null);

try
{
    var schema = Helper.GetSchema<IN202500Content>(client);

    // Export stock items - returns array of string arrays
    var exportCommands = new IN202500Command[]
    {
        schema.StockItemSummary.InventoryID,
        schema.StockItemSummary.Description,
        schema.StockItemSummary.ItemStatus
    };

    // Export with no filter (all records)
    var result = client.Export(exportCommands, null, 0, false, false);

    foreach (var row in result)
    {
        Console.WriteLine($"ID: {row[0]}, Desc: {row[1]}, Status: {row[2]}");
    }
}
finally
{
    client.Logout(); // Always release the session
}
```

### cURL: Quick REST API test

```bash
# Input:  Acumatica instance URL, credentials
# Output: Token + entity list

# Step 1: Get OAuth token
TOKEN=$(curl -s -X POST \
  "https://your-instance.acumatica.com/identity/connect/token" \
  -d "grant_type=password&client_id=YOUR_CLIENT_ID&client_secret=YOUR_SECRET&username=admin&password=YOUR_PASS&scope=api" \
  | jq -r '.access_token')

# Step 2: List available entities on the Default endpoint
curl -s "https://your-instance.acumatica.com/entity/Default/24.200.001/" \
  -H "Authorization: Bearer $TOKEN" | jq '.[].name'

# Step 3: Query a specific entity
curl -s "https://your-instance.acumatica.com/entity/Default/24.200.001/Customer?\$top=5" \
  -H "Authorization: Bearer $TOKEN" | jq .

# Step 4: Execute an action (e.g., release a sales order)
curl -X POST \
  "https://your-instance.acumatica.com/entity/Default/24.200.001/SalesOrder/ReleaseOrder" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"entity": {"OrderType": {"value": "SO"}, "OrderNbr": {"value": "000042"}}}'
```

## Data Mapping

### Screen-Based vs REST Field Mapping

| Screen-Based Field Path | REST API Field | Type | Transform | Gotcha |
|---|---|---|---|---|
| `OrderSummary.OrderType` | `OrderType.value` | String | Direct | REST wraps values in `{value: ...}` objects [src3, src4] |
| `OrderSummary.CustomerID` | `CustomerID.value` | String | Direct | Must match exact customer ID format [src3] |
| `DocumentDetails.InventoryID` | `Details[].InventoryID.value` | String | Array nesting differs | Screen-based uses flat commands; REST uses nested JSON arrays [src3, src4] |
| `OrderSummary.OrderTotal` | `OrderTotal.value` | Decimal | Direct | Read-only in both APIs (calculated field) [src3] |
| `Actions.ReleaseOrder` | `POST .../SalesOrder/ReleaseOrder` | Action | Different invocation | Screen-based: include in Submit() commands; REST: separate POST call [src3, src4] |
| `RowNumber (Export)` | `$skip` / `$top` | Pagination | Different mechanisms | Screen-based Export() returns all rows; REST uses OData pagination [src3, src4] |

### Data Type Gotchas

- **REST API wraps all values in objects**: Every field value in the REST API is `{"value": actual_value}`, not a bare value. Screen-based API uses typed properties directly. Failing to wrap values in the REST API returns validation errors. [src3]
- **Date formats differ**: Screen-based API uses .NET DateTime serialization; REST API uses ISO 8601 (`2026-03-02T00:00:00`). Ensure date parsing handles both formats. [src3, src4]
- **Custom fields have different paths**: In screen-based API, custom fields appear by their screen control name; in REST API, custom fields must be explicitly added to the endpoint configuration on SM207000 before they are accessible. [src7]

## Error Handling & Failure Points

### Common Error Codes

| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 429 | Rate limit exceeded | Too many API requests per minute | Implement exponential backoff; check SM604000 for your rate limit. Requests are throttled at 50% of limit, rejected at 100%. [src6] |
| 401 | Unauthorized | Expired or invalid OAuth token, or failed Login() | Re-authenticate. For screen-based, call Login() again. For REST, obtain a new access token. [src3] |
| 403 | Forbidden | User lacks permissions for the requested operation | Check the API user's roles and permissions in Acumatica's security settings. [src6] |
| 500 | Internal Server Error | Business logic validation failure, lock conflict, or server error | Check the Acumatica trace log for details. Common cause: required field missing or business rule violated. [src4] |
| 511 | Data size limit exceeded | Response payload too large | Add filters ($filter, $top) to reduce result set size. [src3] |
| Login limit error | API user session limit reached | All licensed API user slots are in use | Call Logout() on idle sessions. Increase licensed API user count if needed. [src6] |

[src3, src4, src6]

### Failure Points in Production

- **Session leak on screen-based API**: If Login() is called but Logout() is never called (e.g., exception before Logout()), the API session persists until server timeout. Over time, this exhausts all licensed API user slots. Fix: `Wrap all screen-based API calls in try/finally blocks. Always call Logout() in the finally block.` [src4, src6]
- **Schema cache stale after Acumatica upgrade**: The PX.Soap.dll wrapper caches screen schemas locally. After an Acumatica version upgrade that changes form layouts, the cached schema becomes stale, causing field mapping errors. Fix: `Delete the locally cached schema files after each Acumatica upgrade. The wrapper will re-fetch from the server on next GetSchema() call.` [src4]
- **REST endpoint version mismatch**: Using an old endpoint version (e.g., 17.200.001) that has been removed causes 404 errors. Fix: `Always use the latest endpoint version. Update the version number in all API URLs after each Acumatica upgrade. Current: 24.200.001.` [src2, src7]
- **Rate throttling causes cascade delays**: At 50% of the per-minute rate limit, Acumatica starts delaying (not rejecting) requests. This can cause timeouts in integration middleware that expects fast responses. Fix: `Set HTTP client timeouts higher than the potential throttle delay. Implement retry logic with exponential backoff. Monitor SM604000 for approaching limits.` [src6]
- **Custom field not visible in REST API**: Adding a custom field to a screen in Acumatica does not automatically expose it through the REST API. Fix: `Go to SM207000 (Web Service Endpoints), select your endpoint, navigate to the entity, and add the custom field to the endpoint mapping.` [src7]

## Anti-Patterns

### Wrong: Using screen-based API for standard CRUD in new projects

```csharp
// BAD - screen-based API for simple CRUD is fragile and verbose
var client = new AR303000Screen(); // Customer screen
client.Login(user, pass, company, null, null);
var schema = Helper.GetSchema<AR303000Content>(client);
var cmds = new AR303000Command[] {
    schema.CustomerSummary.CustomerID,
    schema.CustomerSummary.CustomerName
};
var result = client.Export(cmds, null, 0, false, false);
// Breaks if AR303000 form layout changes in next Acumatica version
```

### Correct: Use REST API for standard CRUD

```python
# GOOD - REST API is decoupled from UI, stable across versions
resp = requests.get(
    f"{base_url}/entity/Default/24.200.001/Customer?$top=100",
    headers={"Authorization": f"Bearer {token}"}
)
customers = resp.json()
# Stable across Acumatica versions as long as endpoint version is supported
```

### Wrong: Forgetting to call Logout() on screen-based API

```csharp
// BAD - session leak exhausts API user license slots
var client = new SO301000Screen();
client.Login(user, pass, company, null, null);
var result = client.Export(commands, null, 0, false, false);
// No Logout() call - session stays open until server timeout!
```

### Correct: Always wrap in try/finally with Logout()

```csharp
// GOOD - guaranteed session release
var client = new SO301000Screen();
client.Login(user, pass, company, null, null);
try
{
    var result = client.Export(commands, null, 0, false, false);
    // Process results
}
finally
{
    client.Logout(); // Always release the session
}
```

### Wrong: Hardcoding endpoint version numbers without upgrade plan

```python
# BAD - version 17.200.001 was removed in 2023 R2, breaking this code
resp = requests.get(f"{base_url}/entity/Default/17.200.001/Customer")
```

### Correct: Use latest endpoint version and centralize version config

```python
# GOOD - centralized version, easy to update on Acumatica upgrade
API_VERSION = "24.200.001"
ENDPOINT_NAME = "Default"

resp = requests.get(
    f"{base_url}/entity/{ENDPOINT_NAME}/{API_VERSION}/Customer",
    headers=headers
)
```

## Common Pitfalls

- **Confusing contract-based SOAP with screen-based SOAP**: Acumatica had two different SOAP APIs. The contract-based SOAP endpoints (17.200, 18.200) were removed in 2023 R2. The screen-based SOAP endpoints (per-form .asmx) remain. The community thread announcing the removal confused many developers. Fix: `Check which SOAP type your integration uses. If it uses /entity/ URLs, it's contract-based (migrate to REST). If it uses /Soap/{FormID}.asmx, it's screen-based (still supported).` [src2]
- **Not configuring custom endpoints for REST API**: The Default endpoint only exposes standard entities. Custom entities, fields, and actions require explicit configuration on SM207000. Fix: `Before starting REST development, review SM207000 to ensure all needed entities and fields are mapped. Create custom endpoints for non-standard entities.` [src7]
- **Ignoring push notifications for change tracking**: Polling the API for changes wastes API calls and hits rate limits. Fix: `Configure Push Notifications on SM302000 to trigger webhooks when records change. This is event-driven and does not consume API rate limit quota.` [src3]
- **Using Export() without TopCount for large datasets**: Screen-based Export() without a record limit attempts to return all records at once, causing timeouts and memory issues. Fix: `Always set a reasonable TopCount parameter (e.g., 1000) and implement pagination by tracking the last exported record's key.` [src4]
- **Testing with admin account, deploying with restricted API user**: Everything works in development because the admin account has full access. Production API user has restricted roles, causing 403 errors. Fix: `Test with the actual API user account in a staging environment before deploying. Verify all required screen access rights are granted.` [src6]
- **Not handling the value wrapper in REST API responses**: REST API returns `{"value": "actual_data"}` objects, not bare values. Deserializing without accounting for this wrapper causes null reference errors. Fix: `Define proper DTOs with Value properties, or use Acumatica's official REST API client for C# from GitHub.` [src3]

## Diagnostic Commands

```bash
# Check available REST API endpoints and versions
curl -s "https://your-instance.acumatica.com/entity/" \
  -H "Authorization: Bearer $TOKEN" | jq .

# List all entities on the Default endpoint
curl -s "https://your-instance.acumatica.com/entity/Default/24.200.001/" \
  -H "Authorization: Bearer $TOKEN" | jq '.[].name'

# Test authentication (should return 200 with entity list)
curl -s -o /dev/null -w "%{http_code}" \
  "https://your-instance.acumatica.com/entity/Default/24.200.001/" \
  -H "Authorization: Bearer $TOKEN"

# Check screen-based WSDL is available (browser or curl)
curl -s "https://your-instance.acumatica.com/Soap/SO301000.asmx?WSDL" | head -20

# Verify API user licensing (requires admin access to SM604000)
# Navigate to: https://your-instance.acumatica.com/Main?ScreenId=SM604000
# Check: Maximum Number of Web Services API Users
# Check: Current API User Sessions

# Test REST API rate limit status (monitor response times)
for i in $(seq 1 10); do
  time curl -s -o /dev/null \
    "https://your-instance.acumatica.com/entity/Default/24.200.001/Customer?\$top=1" \
    -H "Authorization: Bearer $TOKEN"
done
```

## Version History & Compatibility

| API Version / Release | Release Date | Status | Breaking Changes | Migration Notes |
|---|---|---|---|---|
| 2024 R2 (24.200) | 2024-10 | Current | New OData URLs introduced | Legacy OData URLs supported until 2025 R2 [src3] |
| 2024 R1 (24.100) | 2024-04 | Supported | None | — |
| 2023 R2 (23.200) | 2023-10 | Supported | Contract-based SOAP endpoints (17.200, 18.200) removed | Migrate to REST API. Screen-based SOAP not affected. [src2] |
| 2023 R1 (23.100) | 2023-04 | Supported | None | Last version with contract-based SOAP endpoints |
| 2021 R2 (21.200) | 2021-08 | EOL | ODBC connectivity removed | Use OData or REST API instead [src5] |
| 2016 (5.3) | 2016 | EOL | N/A | Contract-based API introduced [src1] |

[src1, src2, src3, src5]

### Deprecation Policy

Acumatica follows a phased approach to API deprecation. Contract-based SOAP endpoints were deprecated with a multi-version warning before removal in 2023 R2. Screen-based SOAP endpoints remain supported with no announced end-of-life date, though Acumatica recommends REST for all new development. OData legacy URLs are given at least one major version of overlap before removal. Always check the Developer Release Notes for each new Acumatica version. [src2, src3]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| You need to automate a processing screen action not exposed via REST (e.g., custom release process, specific form button) | Building a new standard CRUD integration | Contract-based REST API [src1, src3] |
| Maintaining an existing screen-based integration that works reliably | Starting a greenfield integration project | Contract-based REST API [src1] |
| You need to interact with every field on a form exactly as a user would | You only need to read/write business objects | Contract-based REST API or OData [src3] |
| Your client is .NET and you can use the PX.Soap.dll wrapper | Your client is Python, JavaScript, Java, or any non-.NET language | Contract-based REST API [src4] |
| You need Export() for bulk data extraction from a specific screen | You need BI/reporting data access | OData (GI-based or DAC-based) [src3] |

## Important Caveats

- The screen-based API has no announced end-of-life date, but Acumatica is investing exclusively in the contract-based REST API for new features. The screen-based API is effectively in maintenance mode. Plan migrations accordingly. [src1, src2]
- Rate limits and API user session limits are license-dependent and vary by Acumatica edition and contract. There are no published universal numbers -- always check SM604000 in your specific instance. [src6]
- Screen-based SOAP endpoints and contract-based SOAP endpoints are two completely different APIs that happen to both use SOAP. The removal of contract-based SOAP in 2023 R2 does NOT affect screen-based SOAP. This is a common source of confusion. [src2]
- The PX.Soap.dll wrapper caches form schemas locally. After any Acumatica upgrade that modifies screens, you must clear the cached schemas or your integration may reference outdated field paths. [src4]
- Acumatica's push notifications and webhooks (SM302000, SM304000) are the recommended event-driven pattern. Do not poll the API for changes -- it wastes rate limit quota and creates unnecessary load. [src3]

## Related Units

- [Acumatica contract-based REST API capabilities](/business/erp-integration/acumatica-rest-api/2026)
