---
# === IDENTITY ===
id: business/erp-integration/sage-x3-web-services/2026
canonical_question: "How do Sage X3 SOAP-based web services work and what are their limitations?"
aliases:
  - "Sage X3 SOAP web services WSDL endpoint and operations"
  - "Sage X3 CAdxWebServiceXmlCC API capabilities and pool configuration"
  - "Sage X3 web services data volume licensing limits WSSIZELIMIT"
  - "Sage X3 SOAP vs REST API integration comparison"
entity_type: erp_integration
domain: business > erp-integration > sage-x3-web-services
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Sage X3 (Enterprise Management)"
    vendor: "Sage"
    version: "V12 (PU9+)"
    edition: "All editions (Standard, Premium)"
    deployment: "hybrid"
    api_surface: "SOAP (RPC/encoded)"

# === VERIFICATION ===
last_verified: 2026-03-02
confidence: 0.88
version: 1.0
first_published: 2026-03-02

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: evolving
  last_breaking_change: "PU9 - WSDL endpoint URL changed, authentication moved to HTTP Basic"
  next_review: 2026-08-29
  change_sensitivity: medium

# === CONSTRAINTS ===
constraints:
  - "SOAP services use RPC/encoded style, not Document/Literal - many modern SOAP clients have limited RPC/encoded support"
  - "Data volume is license-controlled via WSSIZELIMIT/WSPERIOD - exceeding the limit triggers speed throttling, not hard rejection"
  - "Pool size per node.js process is bounded by Maximum Size setting - no auto-scaling beyond configured maximum"
  - "Number of Web service child processes must be >= 1 on the host, otherwise HTTP 500 errors occur"
  - "Objects must be explicitly published as web services before they are accessible via SOAP"
  - "Any change to Entry Transaction, Screen, Object, or Windows requires re-validation and web service republication"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs REST/SData 2.0 API access to Sage X3 (read-only or service-oriented modules)"
    use_instead: "business/erp-integration/sage-x3-rest-api/2026"
  - condition: "User needs Sage Intacct (cloud accounting) integration, not Sage X3"
    use_instead: "business/erp-integration/sage-intacct-api/2026"
  - condition: "User needs Sage 100/200/300 integration"
    use_instead: "N/A - different product line with different API architecture"

# === 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)"
      - "import/export (file-based data exchange)"
      - "subprogram execution (custom business logic)"
  - key: data_volume
    question: "What's your daily data volume?"
    type: choice
    options:
      - "< 1,000 records/day"
      - "1,000-10,000 records/day"
      - "> 10,000 records/day"
  - key: direction
    question: "What's the data flow direction?"
    type: choice
    options:
      - "inbound (writing to Sage X3)"
      - "outbound (reading from Sage X3)"
      - "bidirectional sync"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/sage-x3-web-services/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/sage-x3-rest-api/2026"
      label: "Sage X3 REST/SData 2.0 Web API capabilities"
  solves:
    - id: "business/erp-integration/sage-x3-data-migration/2026"
      label: "Sage X3 data migration playbook using import/export web services"
  alternative_to:
    - id: "business/erp-integration/sage-intacct-api/2026"
      label: "Sage Intacct REST API (different Sage product, modern REST-native)"
  often_confused_with:
    - id: "business/erp-integration/sage-x3-rest-api/2026"
      label: "Sage X3 REST/SData API - different protocol, read-only on classic modules"

# === SOURCES ===
sources:
  - id: src1
    title: "SOAP Web services implementation - Sage X3 Online Help (V12)"
    author: Sage
    url: https://online-help.sagex3.com/erp/12/en-us/Content/V7DEV/api-guide_soap-web-services.html
    type: official_docs
    published: 2025-01-15
    reliability: authoritative
  - id: src2
    title: "Web services integration overview - Sage X3 Online Help (V12)"
    author: Sage
    url: https://online-help.sagex3.com/erp/12/en-us/Content/V7DEV/integration-guide_ws-overview.html
    type: official_docs
    published: 2025-01-15
    reliability: authoritative
  - id: src3
    title: "Classic SOAP pools configuration - Sage X3 Online Help"
    author: Sage
    url: https://online-help.sagex3.com/erp/11/en-US/V7DEV/administration-reference_soapClassicPool.html
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
  - id: src4
    title: "Consuming X3 SOAP Web Services in Update 9 from .NET"
    author: RKL eSolutions
    url: https://www.rklesolutions.com/blog/x3-soap-web-services
    type: technical_blog
    published: 2024-03-15
    reliability: moderate_high
  - id: src5
    title: "Sage X3 Web Services Troubleshooting"
    author: RKL eSolutions
    url: https://www.rklesolutions.com/blog/troubleshooting-x3-web-services
    type: technical_blog
    published: 2024-05-10
    reliability: moderate_high
  - id: src6
    title: "Solving Web Service Pools and Integrations Issues in Sage X3"
    author: RKL eSolutions
    url: https://www.rklesolutions.com/blog/web-service-pools-and-integration-in-sage-x3
    type: technical_blog
    published: 2024-07-20
    reliability: moderate_high
  - id: src7
    title: "SOAP Web services import/export example - Sage X3 Online Help (V12)"
    author: Sage
    url: https://online-help.sagex3.com/erp/12/en-us/Content/V7DEV/api-guide_api-soap-import-export-example.html
    type: official_docs
    published: 2025-01-15
    reliability: authoritative
  - id: src8
    title: "5 Days of Sage X3 Web Services v12 - Day 1: SOAP Pool Setup"
    author: RKL eSolutions
    url: https://www.rklesolutions.com/blog/5-days-sage-x3-web-services-v12-day-1
    type: technical_blog
    published: 2024-02-01
    reliability: moderate_high
---

# Sage X3 SOAP Web Services: Architecture, Operations, and Limitations

## TL;DR

- **Bottom line**: Sage X3 exposes SOAP web services via the CAdxWebServiceXmlCC generic service using RPC/encoded style. Published X3 objects and subprograms are callable through CRUD, query, import/export, and subprogram operations. For new development, evaluate whether the REST/SData 2.0 Web API meets your needs first - SOAP is the only option for write operations on classic (non-service-oriented) modules. [src1, src2]
- **Key limit**: Data volume is license-controlled (WSSIZELIMIT in MB per WSPERIOD). Exceeding the limit does not reject calls but progressively throttles speed by the WSGRACESLOWDOWN factor. Pool concurrency is bounded by the Maximum Size setting per node.js process. [src1]
- **Watch out for**: The WSDL endpoint URL changed in PU9 from `/adxwsvc/services/CAdxWebServiceXmlCC?wsdl` to `/soap-wsdl/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC?wsdl`. The old WSDL still validates but calls silently fail at runtime. [src4]
- **Best for**: Write operations (create, modify, delete) on classic X3 objects, import/export file-based data exchange, and executing custom subprograms. [src1, src2]
- **Authentication**: Basic authentication (username/password) for on-premise; OAuth 2.0 for Sage X3 Online (cloud). Certificate authentication available for on-premise. [src2]

## System Profile

Sage X3 (also known as Sage Enterprise Management) is a mid-market ERP system that exposes its business logic through SOAP web services. The SOAP interface has been available since V6 and remains the primary mechanism for write operations on classic modules - the REST/SData 2.0 Web API provides read-only access to classic module data. This card covers the SOAP web services architecture in V12 (PU9 and later), which introduced significant changes to endpoint URLs, authentication, and pool management. Earlier versions (PU8 and below) use a different configuration console and endpoint format. [src1, src2, src4]

| Property | Value |
|---|---|
| **Vendor** | Sage |
| **System** | Sage X3 (Enterprise Management) V12 |
| **API Surface** | SOAP (RPC/encoded), via CAdxWebServiceXmlCC |
| **Current API Version** | V12 (PU9+) |
| **Editions Covered** | Standard, Premium (all editions) |
| **Deployment** | Hybrid (on-premise and Sage X3 Online/cloud) |
| **API Docs URL** | [Sage X3 SOAP Web Services](https://online-help.sagex3.com/erp/12/en-us/Content/V7DEV/api-guide_soap-web-services.html) |
| **Status** | GA (maintenance - Sage is progressively migrating to REST/SData 2.0) |

## API Surfaces & Capabilities

Sage X3 offers two primary API surfaces. SOAP is the mature, full-featured option for classic modules. REST (SData 2.0) is the modern successor, but only supports write operations on service-oriented (migrated) modules. [src1, src2]

| API Surface | Protocol | Best For | Operations | Rate Limit | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| SOAP (CAdxWebServiceXmlCC) | HTTPS/XML (RPC/encoded) | Write operations on classic objects, subprogram execution | CRUD, query, import, export, subprogram | License-based (WSSIZELIMIT MB/period) | Yes | Via import/export |
| REST Web API (SData 2.0) | HTTPS/JSON | Read operations on all modules, write on service-oriented modules | GET, POST, PUT, DELETE | License-based | Yes | No native bulk |
| SOAP Import/Export | HTTPS/XML | File-based batch data exchange | AOWSIMPORT, AOWSEXPORT | Shared with SOAP limit | No (batch) | Yes |

[src1, src2, src7]

## Rate Limits & Quotas

### Per-Request Limits

| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max records per query (listSize) | Configurable per call | SOAP query operations | Set via `listSize` parameter in the SOAP request; no hard system maximum documented |
| Max pool clients per node.js process | Configured via Maximum Size | SOAP pool | Typical range: 2-10 clients per pool |
| Unused client timeout | 20 min (default) | Individual pool client | Idle clients are automatically stopped after this period |
| Client life timeout | 720 min / 12 hours (default) | Individual pool client | Channels reset after this duration regardless of activity |

[src1, src3]

### Rolling / Daily Limits

| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| Data volume (WSSIZELIMIT) | License-dependent (MB) | DAY, MONTH, or YEAR (WSPERIOD) | Varies by license tier; not publicly documented per-edition |
| Grace overage (WSGRACELIMIT) | Typically 10% above WSSIZELIMIT | Same as WSPERIOD | Calls continue but speed degrades |
| Throttle factor (WSGRACESLOWDOWN) | Speed divided by configured factor (e.g., 5x) | Until period resets | When 1 MB daily limit reached, speed divided by 5 until end of day |

[src1]

### Concurrency Limits

| Limit Type | Value | Notes |
|---|---|---|
| Pool initialization size | Configurable (e.g., 2) | Clients created at pool startup per node.js process |
| Pool maximum size | Configurable (e.g., 4-10) | Maximum concurrent clients per node.js process |
| Web service child processes | >= 1 required on host | Set via Administration > Servers > Hosts; 0 = HTTP 500 errors |
| Initialization size limit | Avoid > 8 | Setting initialization size above 8 may cause timeout errors during pool start/stop |

[src1, src3, src5]

## Authentication

Sage X3 SOAP web services support three authentication mechanisms, with availability depending on deployment model. [src2]

| Flow | Use When | Deployment | Credential Storage | Notes |
|---|---|---|---|---|
| Basic Authentication (HTTP) | On-premise integrations, simplest setup | On-premise only | Username/password in HTTP Authorization header | PU9+ moved auth from SOAP context to HTTP headers. Password must be set to never expire. [src4, src5] |
| Certificate Authentication | On-premise production environments requiring higher security | On-premise only | X.509 certificate | SSL client certificate presented with each request |
| OAuth 2.0 | Sage X3 Online (cloud) - mandatory | Cloud only | Bearer token in Authorization header | Only method available in Sage X3 Online; configure via Sage ID |

[src2, src4]

### Authentication Gotchas

- **PU9 changed authentication from SOAP context to HTTP headers**: Before PU9, username and password were passed in the CAdxCallContext SOAP body. PU9+ requires HTTP Basic Authentication headers. Old integration code that embeds credentials in the SOAP context will silently authenticate against the wrong user or fail. [src4]
- **Web service user must have explicit authorization**: The X3 user account must be specifically authorized for web services access in Setup > Users > Users. A standard user account without this flag will be rejected. [src5]
- **User password must never expire**: The web service user account must be configured with "password never expires" and standard authentication type. Expired passwords cause pool startup failures. [src5]
- **OAuth 2.0 is cloud-only**: Basic and certificate authentication are unavailable on Sage X3 Online. OAuth 2 is unavailable on on-premise deployments unless specifically configured with an external identity provider. [src2]

## Constraints

- **RPC/encoded SOAP style limits client compatibility** - many modern SOAP libraries and code generators default to Document/Literal and have poor or no support for RPC/encoded. Java (JAX-WS) and .NET require custom configuration or workarounds. [src1, src4]
- **Objects must be explicitly published as web services** - unlike REST APIs that expose all resources by default, SOAP services only work with objects that have been specifically published through the Sage X3 administration console. Unpublished objects return errors. [src5]
- **Any object modification requires republication** - changes to Entry Transactions, Screens, Objects, or Windows associated with a published web service require re-validation of each changed entity AND republication of the web service. Failing to republish causes silent data errors or failures. [src5]
- **Pool clients consume server resources even when idle** - each initialized client holds an active connection to the X3 runtime. Over-provisioning pools degrades server performance; under-provisioning causes request queuing. [src3, src6]
- **Data volume licensing controls throughput, not access** - the license does not reject calls when limits are exceeded; instead, it progressively throttles response speed by the WSGRACESLOWDOWN factor, making integrations unpredictably slow without clear error messages. [src1]
- **SOAP services are in maintenance mode** - Sage is progressively migrating modules to service-oriented architecture with REST/SData 2.0. New features and improvements are focused on the REST API, not SOAP. [src2]

## Integration Pattern Decision Tree

```
START - User needs to integrate with Sage X3
|-- What operations are needed?
|   |-- Read-only data access
|   |   |-- Module is service-oriented (migrated)?
|   |   |   |-- YES --> Use REST/SData 2.0 Web API (simpler, JSON, modern)
|   |   |   |-- NO --> REST provides read-only representations; sufficient for reads
|   |   |-- Need complex queries with criteria?
|   |       |-- YES --> SOAP query with listSize and criteria parameters
|   |       |-- NO --> REST GET with $filter is simpler
|   |-- Write operations (create, modify, delete)
|   |   |-- Module is service-oriented?
|   |   |   |-- YES --> REST POST/PUT/DELETE available
|   |   |   |-- NO --> SOAP is required (only write path for classic modules) [src2]
|   |-- Batch import/export
|   |   --> SOAP import/export (AOWSIMPORT/AOWSEXPORT) operations [src7]
|   |-- Execute custom business logic (subprograms)
|       --> SOAP subprogram call (only available via SOAP) [src1]
|-- What's the deployment model?
|   |-- On-premise --> Basic auth or certificate auth
|   |-- Sage X3 Online (cloud) --> OAuth 2.0 (mandatory) [src2]
|-- What's the data volume?
|   |-- < WSSIZELIMIT per period --> Normal speed
|   |-- > WSSIZELIMIT --> Speed throttled by WSGRACESLOWDOWN factor
|   |-- > WSSIZELIMIT + WSGRACELIMIT --> Maximum throttling until period resets [src1]
|-- Pool sizing?
    |-- Low volume (< 100 calls/hour) --> Init: 1, Max: 2
    |-- Medium volume (100-1000 calls/hour) --> Init: 2, Max: 4-6
    |-- High volume (> 1000 calls/hour) --> Init: 4, Max: 8 (avoid > 8 init size)
    |-- Schedule periodic pool restarts (daily/weekly) for stability [src6]
```

## Quick Reference

| Operation | SOAP Action | Key Parameters | Response Fields | Notes |
|---|---|---|---|---|
| Read record | `read` | `publicName`, `objectKeys` (key fields) | `resultXml`, `status`, `messages` | Returns single record by primary key [src1] |
| Create record | `save` | `publicName`, `objectXml` (field values) | `resultXml`, `status`, `messages` | Creates new record; returns created object [src1] |
| Modify record | `modify` | `publicName`, `objectKeys`, `objectXml` | `resultXml`, `status`, `messages` | Updates existing record by key [src1] |
| Delete record | `delete` | `publicName`, `objectKeys` | `status`, `messages` | Deletes record by primary key [src1] |
| Query records | `query` | `publicName`, `objectKeys`, `listSize` | `resultXml` (list), `status` | Returns filtered list; set listSize for pagination [src1] |
| Export data | `run` (AOWSEXPORT) | `I_MODEXP`, `I_TCRITERE`, `I_EXEC` | `O_FILE`, `status` | File-based export with record separator [src7] |
| Import data | `run` (AOWSIMPORT) | `I_MODIMP`, `I_FILE`, `I_EXEC` | `status`, `messages` | File-based import; validate template first [src7] |
| Run subprogram | `run` | `publicName`, input parameters | Output parameters, `status` | Executes custom X3 subprogram [src1] |
| Get WSDL | GET | N/A | WSDL XML | `/soap-wsdl/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC?wsdl` [src1, src4] |

## Step-by-Step Integration Guide

### 1. Configure the SOAP pool in Syracuse administration

Navigate to Administration > Administration > Web Services > Classic SOAP pools configuration. Create a pool with alias, endpoint, locale, user, password, initialization size, and maximum size. Always enable "Auto start" so the pool starts with the Syracuse server. [src3, src8]

```plaintext
Pool Configuration:
  Alias:             MYPOOL
  Endpoint:          MAIN (your X3 endpoint name)
  Locale:            English (United States)
  User:              WSUSER (dedicated web service user)
  Password:          (web service user password)
  Maximum Size:      4
  Initialization Size: 2
  Auto Start:        checked
```

**Verify**: Navigate to the pool list and confirm status shows green (active). Click "Status" to see client count and queue metrics.

### 2. Set up the web service user in X3

Create or configure a dedicated user for web services in Setup > Users > Users. The user must have web services connection authorization, standard authentication type, and password set to never expire. [src5]

```plaintext
User Setup:
  Login:              WSUSER
  Last Name:          WebService
  Group:              (appropriate security group)
  Authentication:     Standard
  Password Expires:   Never
  Web Services Auth:  Enabled
```

**Verify**: Attempt to log in as the WSUSER via the X3 web interface to confirm the account is active and has appropriate permissions.

### 3. Publish the target object as a web service

Navigate to Administration > Web Services > Classic SOAP Web services. Select the object you want to expose (e.g., SOH for Sales Orders) and publish it. If the object was previously published and modified, re-validate all changed entities before republishing. [src5]

```plaintext
Publication Steps:
1. Administration > Web Services > Classic SOAP Web services
2. Select the object to publish (e.g., SOH - Sales Orders)
3. Click "Publish" (or "Save" if re-publishing after changes)
4. Verify the web service appears in the published list
```

**Verify**: Use the built-in web service tester (Administration > Web Services > Classic SOAP Web services > Test) to invoke a read operation and confirm data returns.

### 4. Consume the WSDL and make a SOAP call

Retrieve the WSDL from the Syracuse server and generate client stubs. For PU9+, use the new endpoint URL format. Add HTTP Basic Authentication headers to all requests. [src1, src4]

```python
# Input:  Syracuse server URL, pool alias, X3 credentials
# Output: Query results from a published web service object

import requests
from requests.auth import HTTPBasicAuth

SYRACUSE_URL = "https://your-x3-server:8124"
POOL_ALIAS = "MYPOOL"
WS_USER = "WSUSER"
WS_PASS = "your_password"
PUBLIC_NAME = "SOH"  # Published web service name

# SOAP envelope for a query operation
soap_body = f"""<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:wss="http://www.adonix.com/WSS">
  <soapenv:Body>
    <wss:query>
      <callContext>
        <codeLang>ENG</codeLang>
        <poolAlias>{POOL_ALIAS}</poolAlias>
        <requestConfig>adxwss.optreturn=JSON&amp;adxwss.beautify=true</requestConfig>
      </callContext>
      <publicName>{PUBLIC_NAME}</publicName>
      <objectKeys>
        <key/>
      </objectKeys>
      <listSize>10</listSize>
    </wss:query>
  </soapenv:Body>
</soapenv:Envelope>"""

response = requests.post(
    f"{SYRACUSE_URL}/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC",
    data=soap_body,
    headers={"Content-Type": "text/xml; charset=utf-8"},
    auth=HTTPBasicAuth(WS_USER, WS_PASS),
    verify=True  # set to False only for self-signed certs in dev
)

print(f"Status: {response.status_code}")
print(response.text)
```

**Verify**: Response contains `<status>1</status>` (success) and `resultXml` with the queried records in JSON format.

## Code Examples

### Python: Read a Sales Order by Key

```python
# Input:  Syracuse URL, pool alias, credentials, sales order number
# Output: Sales order details in JSON format

import requests
from requests.auth import HTTPBasicAuth
import xml.etree.ElementTree as ET

SYRACUSE_URL = "https://your-x3-server:8124"
POOL_ALIAS = "MYPOOL"
ORDER_NUMBER = "SO000123"

soap_body = f"""<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:wss="http://www.adonix.com/WSS">
  <soapenv:Body>
    <wss:read>
      <callContext>
        <codeLang>ENG</codeLang>
        <poolAlias>{POOL_ALIAS}</poolAlias>
        <requestConfig>adxwss.optreturn=JSON</requestConfig>
      </callContext>
      <publicName>SOH</publicName>
      <objectKeys>
        <key>{ORDER_NUMBER}</key>
      </objectKeys>
    </wss:read>
  </soapenv:Body>
</soapenv:Envelope>"""

resp = requests.post(
    f"{SYRACUSE_URL}/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC",
    data=soap_body,
    headers={"Content-Type": "text/xml; charset=utf-8"},
    auth=HTTPBasicAuth("WSUSER", "password"),
    verify=True
)

# Parse status from SOAP response
root = ET.fromstring(resp.text)
ns = {"wss": "http://www.adonix.com/WSS"}
status = root.find(".//status", ns)
result_xml = root.find(".//resultXml", ns)

if status is not None and status.text == "1":
    print("Success:", result_xml.text)
else:
    messages = root.findall(".//message", ns)
    for msg in messages:
        print("Error:", msg.text)
```

### C#/.NET: Consume SOAP Web Service with Basic Auth

```csharp
// Input:  Syracuse URL, pool alias, web service user credentials
// Output: Query results via CAdxWebServiceXmlCC

// Add Web Reference using:
// https://your-x3-server:8124/soap-wsdl/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC?wsdl

// Custom class to inject Basic Auth headers (required for PU9+)
public class X3WebService : CAdxWebServiceXmlCCService
{
    public string Username { get; set; }
    public string Password { get; set; }

    protected override System.Net.WebRequest GetWebRequest(Uri uri)
    {
        var request = base.GetWebRequest(uri);
        string credentials = Convert.ToBase64String(
            System.Text.Encoding.ASCII.GetBytes($"{Username}:{Password}"));
        request.Headers["Authorization"] = $"Basic {credentials}";
        return request;
    }
}

// Usage:
var service = new X3WebService
{
    Url = "https://your-x3-server:8124/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC",
    Username = "WSUSER",
    Password = "password"
};

var context = new CAdxCallContext
{
    codeLang = "ENG",
    poolAlias = "MYPOOL",
    requestConfig = "adxwss.optreturn=JSON"
};

var result = service.query(context, "SOH", new CAdxParamKeyValue[0], 10);
if (result.status == 1)
    Console.WriteLine(result.resultXml);
else
    foreach (var msg in result.messages)
        Console.WriteLine($"Error: {msg.message}");
```

### cURL: Quick SOAP query test

```bash
# Input:  Syracuse URL, pool alias, credentials
# Output: SOAP response with queried records

# Query the first 5 sales orders
curl -X POST \
  "https://your-x3-server:8124/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC" \
  -u "WSUSER:password" \
  -H "Content-Type: text/xml; charset=utf-8" \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:wss="http://www.adonix.com/WSS">
  <soapenv:Body>
    <wss:query>
      <callContext>
        <codeLang>ENG</codeLang>
        <poolAlias>MYPOOL</poolAlias>
        <requestConfig>adxwss.optreturn=JSON&amp;adxwss.beautify=true</requestConfig>
      </callContext>
      <publicName>SOH</publicName>
      <objectKeys><key/></objectKeys>
      <listSize>5</listSize>
    </wss:query>
  </soapenv:Body>
</soapenv:Envelope>'

# Expected: <status>1</status> with resultXml containing JSON array of sales orders
```

## Data Mapping

### SOAP Response Format Reference

| Response Format | Configuration | Content Structure | Best For |
|---|---|---|---|
| XML (default) | `adxwss.optreturn=XML` | `<RESULT><LIN><FLD NAME="x" TYPE="y">value</FLD></LIN></RESULT>` | Typed data with metadata attributes |
| JSON | `adxwss.optreturn=JSON` | `[{"field1": "value1", "field2": "value2"}]` | Lighter payloads, simpler parsing |
| Beautified | `adxwss.beautify=true` | Same structure with CRLF formatting | Human-readable debugging |

[src1]

### CAdxCallContext Field Reference

| Field | Required | Type | Description | Gotcha |
|---|---|---|---|---|
| `codeLang` | No | String | Language code (ENG, FRA, etc.) or ISO via Accept-Language | Uses pool default if omitted; affects field labels in response |
| `poolAlias` | Yes | String | Pool identifier from Syracuse admin | Must match exactly; case-sensitive |
| `poolId` | No | String | Force specific client in pool | If specified client is busy, request waits instead of using another |
| `requestConfig` | No | String | `&`-separated config params (`adxwss.*`) | Use `&amp;` in XML for `&` separator |

[src1]

### Data Type Gotchas

- **Date fields return in X3 internal format**: Dates may return as `YYYYMMDD` strings rather than ISO 8601. Parse carefully and do not assume ISO format. [src1]
- **Numeric precision depends on X3 field definition**: Currency fields may have variable decimal places based on the X3 object's field configuration, not a standard format. Transform to your target precision explicitly. [src1]
- **Multi-line fields use pipe separator in import/export**: The `I_RECORDSEP` parameter in import/export operations replaces line breaks with the specified character (typically `|`). Your parser must handle this substitution. [src7]
- **Character encoding must be UTF-8**: The SOAP envelope must specify `charset=utf-8`. Non-UTF-8 characters in field values (common with French/German text in X3) cause parsing failures. [src1]

## Error Handling & Failure Points

### Common Error Codes

| Code/Status | Meaning | Cause | Resolution |
|---|---|---|---|
| HTTP 200, `status=0` | Business error | X3 business rule violation (duplicate key, validation failure, missing required field) | Check `messages` array in response for specific X3 error text; fix data and retry [src1] |
| HTTP 200, `status=1` | Success | Operation completed | Check `resultXml` for returned data |
| HTTP 401 | Authentication failed | Wrong username/password or user not authorized for web services | Verify credentials; ensure user has web services authorization in X3 [src5] |
| HTTP 500 | Server error | Pool not started, no web service child processes, or Syracuse crash | Check pool status; verify Number of Web service child processes >= 1 on host [src5] |
| HTTP 500 "No Web services accepted" | Missing child processes | Number of Web services children = 0 on the host definition | Set to >= 1 in Administration > Servers > Hosts [src1] |
| Timeout | Request timeout | Pool clients all busy, long-running X3 operation, or initialization size > 8 | Increase pool maximum size; reduce initialization size to <= 8; increase client timeout [src3, src5] |

[src1, src5]

### Failure Points in Production

- **Pool stops responding after error cascade**: Prior web service errors (e.g., X3 runtime crashes) can leave pool clients in a corrupted state, causing all subsequent calls to hang or fail. Fix: `Schedule automated daily/weekly pool restarts via REST API calls to the stop/start endpoints. Monitor pool status proactively.` [src6]
- **WSDL validates but calls fail after PU9 upgrade**: The old WSDL endpoint (`/adxwsvc/services/...`) still serves a valid WSDL document, but runtime calls against it fail silently. Fix: `Update all integration endpoints to the new URL format: /soap-wsdl/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC?wsdl` [src4]
- **Object modification breaks web service without warning**: Changes to Entry Transactions, Screens, or Objects invalidate the published web service. The "Save" button becomes enabled in the web service definition, indicating it needs republication. Fix: `After ANY object modification, re-validate all changed entities and republish the web service. Include this step in your change management process.` [src5]
- **Data volume throttling causes unpredictable slowdowns**: When WSSIZELIMIT is exceeded, the system does not return an error - it silently throttles speed by the WSGRACESLOWDOWN factor. Integration processes appear to hang or timeout. Fix: `Monitor data volume usage against license limits. Implement logging of CAdxTechnicalInfos.totalDuration to detect progressive slowdowns. Upgrade license if needed.` [src1]
- **Pool client language/user mismatch causes wrong data**: If all clients matching the requested language and user are busy, the pool distributor may assign a client with a different language or user context, returning data in the wrong language or with different permissions. Fix: `Size pools appropriately for concurrent load. Use poolId to force specific client selection for critical operations.` [src1]

## Anti-Patterns

### Wrong: Using the old WSDL endpoint URL after PU9 upgrade

```python
# BAD - old endpoint still returns a WSDL but calls fail at runtime
wsdl_url = "http://x3server:8124/adxwsvc/services/CAdxWebServiceXmlCC?wsdl"
```

### Correct: Use the PU9+ Syracuse WSDL endpoint

```python
# GOOD - correct endpoint for PU9 and later
wsdl_url = "http://x3server:8124/soap-wsdl/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC?wsdl"
```

### Wrong: Embedding credentials in the SOAP context body (pre-PU9 style)

```xml
<!-- BAD - PU9+ ignores credentials in SOAP body; uses HTTP auth instead -->
<callContext>
  <codeLang>ENG</codeLang>
  <poolAlias>MYPOOL</poolAlias>
  <codeUser>ADMIN</codeUser>
  <password>secret</password>
</callContext>
```

### Correct: Use HTTP Basic Authentication headers

```python
# GOOD - PU9+ requires HTTP Basic Auth
import requests
from requests.auth import HTTPBasicAuth

response = requests.post(
    soap_url,
    data=soap_envelope,
    headers={"Content-Type": "text/xml; charset=utf-8"},
    auth=HTTPBasicAuth("WSUSER", "password")  # HTTP-level auth
)
```

### Wrong: Never restarting the pool, assuming indefinite stability

```plaintext
# BAD - pools accumulate state corruption over time
# Set up pool once, never restart, wonder why calls fail after weeks
```

### Correct: Schedule periodic pool restarts

```bash
# GOOD - automated daily pool restart via Syracuse REST API
# Stop pool
curl -X POST \
  "http://x3server:8124/api1/syracuse/collaboration/syracuse/soapClassicPools('POOL_UUID')/$service/stop" \
  -u "admin:password"

# Wait for stop to complete
sleep 10

# Start pool
curl -X POST \
  "http://x3server:8124/api1/syracuse/collaboration/syracuse/soapClassicPools('POOL_UUID')/$service/start" \
  -u "admin:password"
```

[src6]

## Common Pitfalls

- **Over-provisioning pool initialization size**: Setting initialization size > 8 can cause timeout errors during pool startup. Each initialized client consumes server resources (memory, X3 runtime connection). Fix: `Start with initialization size of 2, maximum of 4. Scale up based on observed concurrency needs, never exceeding 8 for initialization.` [src3, src5]
- **Not monitoring CAdxTechnicalInfos performance metrics**: Every SOAP response includes timing data (loadWebsDuration, poolDistribDuration, poolExecDuration, poolWaitDuration, totalDuration). Ignoring these metrics means you miss early warnings of pool saturation and throttling. Fix: `Log technicalInfos from every response. Alert when poolWaitDuration exceeds 5 seconds or totalDuration exceeds 30 seconds.` [src1]
- **Using the web service tester as proof of production readiness**: The built-in X3 tester runs in the same server context with no network latency or authentication overhead. Fix: `Always test from the actual integration client with production-like network conditions, authentication, and concurrent load.` [src5]
- **Ignoring the Save button on web service definitions**: When the Save button becomes enabled on a previously published web service, it means the underlying object has changed and the service needs republication. Fix: `Include web service validation and republication in your change management process for any X3 object or screen modification.` [src5]
- **Assuming REST can replace SOAP for all operations**: The REST/SData 2.0 API only supports write operations on service-oriented (migrated) modules. Most classic modules (manufacturing, purchasing, sales in some editions) still require SOAP for writes. Fix: `Check whether the target module has been migrated to service-oriented architecture before choosing REST. When in doubt, use SOAP.` [src2]
- **Not handling partial success in multi-record operations**: Import operations may partially succeed - some records imported, others rejected. The status code may still return 1 (success) even with partial failures. Fix: `Always parse the messages array for individual record-level errors, even when the overall status is 1.` [src7]

## Diagnostic Commands

```bash
# Get WSDL to verify web service endpoint is accessible
curl -u "WSUSER:password" \
  "https://x3server:8124/soap-wsdl/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC?wsdl" \
  -o wsdl.xml && echo "WSDL retrieved successfully"

# Check pool status via Syracuse REST API
curl -u "admin:password" \
  "http://x3server:8124/sdata/syracuse/collaboration/syracuse/soapClassicPools?representation=soapClassicPool.\$query" \
  -H "Accept: application/json" | python -m json.tool

# Stop a pool (use pool UUID from status query)
curl -X POST -u "admin:password" \
  "http://x3server:8124/api1/syracuse/collaboration/syracuse/soapClassicPools('POOL_UUID')/\$service/stop"

# Start a pool
curl -X POST -u "admin:password" \
  "http://x3server:8124/api1/syracuse/collaboration/syracuse/soapClassicPools('POOL_UUID')/\$service/start"

# Test a simple SOAP read to verify authentication and pool connectivity
curl -X POST -u "WSUSER:password" \
  "https://x3server:8124/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC" \
  -H "Content-Type: text/xml; charset=utf-8" \
  -d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wss="http://www.adonix.com/WSS"><soapenv:Body><wss:query><callContext><codeLang>ENG</codeLang><poolAlias>MYPOOL</poolAlias><requestConfig>adxwss.optreturn=JSON</requestConfig></callContext><publicName>SOH</publicName><objectKeys><key/></objectKeys><listSize>1</listSize></wss:query></soapenv:Body></soapenv:Envelope>'
```

## Version History & Compatibility

| Version | Release | Status | Breaking Changes | Migration Notes |
|---|---|---|---|---|
| V12 PU13+ | 2025+ | Current | None from PU9 | Latest patches; SOAP remains stable |
| V12 PU9 | 2022 | Supported | WSDL URL changed; auth moved to HTTP headers; pool size no longer license-controlled | Update WSDL URLs, add HTTP Basic Auth, reconfigure pools in Syracuse admin [src4] |
| V11 PU8 | 2020 | Legacy | N/A (pre-PU9 baseline) | Uses old `/adxwsvc/` endpoint; credentials in SOAP context; pool size license-controlled |
| V6-V7 | 2012-2016 | EOL | N/A | Original SOAP implementation; Console-based configuration |

[src1, src4]

### Deprecation Policy

Sage does not publish a formal API deprecation timeline for X3 SOAP web services. However, the progressive migration of modules from classic to service-oriented architecture indicates SOAP is in long-term maintenance mode. Sage has not announced a SOAP sunset date, but new development investment is directed toward the REST/SData 2.0 Web API. Plan new integrations with a migration path to REST where possible. [src2]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Write operations (create/modify/delete) on classic X3 modules not yet migrated to service-oriented architecture | Read-only data access where REST/SData 2.0 is available | Sage X3 REST/SData 2.0 Web API |
| Batch import/export of data using X3 templates (AOWSIMPORT/AOWSEXPORT) | Real-time high-frequency integrations (>100 calls/min) with modern systems | Middleware with queue-based architecture or direct database access (with Sage approval) |
| Executing custom X3 subprograms for business logic | Integrating with Sage Intacct (different product) | Sage Intacct REST API |
| On-premise deployments requiring certificate-based auth | Building new integrations when REST/SData 2.0 covers your modules | REST/SData 2.0 (simpler, JSON-native, modern tooling) |
| Legacy integration maintenance where switching APIs is too costly | Greenfield projects with no legacy X3 constraints | Evaluate REST/SData 2.0 first; use SOAP only if REST cannot meet write requirements |

## Important Caveats

- SOAP web services are in maintenance mode. Sage is progressively migrating X3 modules to a service-oriented architecture that supports REST/SData 2.0. New features are not being added to the SOAP layer. [src2]
- Data volume licensing parameters (WSSIZELIMIT, WSPERIOD, WSGRACELIMIT, WSGRACESLOWDOWN) vary by license tier and are not publicly documented. Contact your Sage account manager for your specific limits. [src1]
- Pool behavior and performance characteristics vary significantly between on-premise and Sage X3 Online (cloud) deployments. Cloud deployments have additional infrastructure-level throttling not documented in the API guides.
- The RPC/encoded SOAP style is increasingly unsupported by modern tooling. Test your SOAP client library's compatibility with RPC/encoded before committing to a SOAP integration approach. [src1, src4]
- All configuration, pool management, and web service publication must be done by a Sage X3 administrator with Syracuse access. Integration developers typically cannot self-service these changes.

## Related Units

- [Sage X3 REST/SData 2.0 Web API capabilities](/business/erp-integration/sage-x3-rest-api/2026)
- [Sage Intacct REST API (different Sage product, modern REST-native)](/business/erp-integration/sage-intacct-api/2026)
