Sage Intacct API: REST & XML Web Services Capabilities, Rate Limits, and Session Management

Type: ERP Integration System: Sage Intacct (REST API v1 / XML DTD 3.0) Confidence: 0.88 Sources: 8 Verified: 2026-03-02 Freshness: 2026-03-02

TL;DR

System Profile

Sage Intacct is a cloud-native financial management system widely used in mid-market organizations ($10M-$1B revenue). It offers two API surfaces with different authentication models, capabilities, and maturity levels. The REST API (v1) was introduced to modernize integrations and is where Sage invests new feature development. The XML Web Services API (DTD 3.0) provides comprehensive access to the full Sage Intacct feature set and remains the primary integration surface for complex financial transactions. Sage provides official SDKs for the XML API in .NET, Node.js, and PHP.

PropertyValue
VendorSage
SystemSage Intacct
API SurfaceREST API v1 (JSON) + XML Web Services (DTD 3.0)
Current API VersionREST v1 / XML DTD 3.0
Editions CoveredEssentials, Standard, Premium (all editions)
DeploymentCloud (multi-tenant SaaS)
API DocsREST API / XML API
StatusREST: GA (expanding coverage) / XML: GA (full coverage, maintenance)

API Surfaces & Capabilities

API SurfaceProtocolBest ForMax Records/RequestRate LimitReal-time?Bulk?
REST API v1HTTPS/JSONModern integrations, GL, AP, AR, cash managementPaginated (varies)100K txn/month (Tier 1)YesLimited
XML Web Services (DTD 3.0)HTTPS/XMLFull feature set, complex transactions, project accounting, fixed assets100 records recommended100K txn/month, 2 concurrentYesYes (batched)
XML Web Services (Legacy DTD 2.1)HTTPS/XMLLegacy integrations onlySame as DTD 3.0Shared with DTD 3.0YesYes
Smart Events/TriggersPlatform eventsEvent-driven automationN/APlatform-dependentYesN/A
CSV ImportFile uploadBulk data loadingVaries by objectN/ANoYes

Rate Limits & Quotas

Per-Request Limits

Limit TypeValueApplies ToNotes
Max records per query1,000 (recommended)XML API readByQuery/queryUse pagination (resultId) for larger sets
Max records per manipulation100 (recommended)XML API create/update/deleteLarger batches risk 15-min timeout
Max request processing time15 minutesXML APIGateway returns timeout; backend may still process
Max concurrent connections (default)2 per tenantBoth APIs3rd request held ~30s then rejected
Max concurrent connections (per-app)6 (app) / 8 (company total)Higher tiersContractual; contact CSM to upgrade

Rolling / Daily Limits

Limit TypeValueWindowEdition Differences
API transactions (Tier 1)100,000MonthlyDefault for all editions; overage charged, not blocked
API transactions (Tier 2-4)Up to 2,500,000MonthlyPremium tiers; contact CSM for pricing
API transactions (Tier 5)Custom / unlimitedMonthlyEnterprise agreement
Overage fee (Tier 1)$0.15 per 10-txn packPer-monthCharged retroactively

Transaction Counting Rules

OperationTransaction CountNotes
Single create/update/delete1Each API function call counted individually
Header + line items (e.g., AP bill with 50 lines)1Header objects count as 1 regardless of line items
Batch of 100 vendor creates in one request100Each function call is a separate transaction
query/readByQuery1Each query counts as 1 transaction
getAPISession1Session creation is a transaction

Authentication

REST API Authentication (OAuth 2.0)

FlowUse WhenToken LifetimeRefresh?Notes
Authorization CodeUser-context operations, interactive appsJWT-based (configurable)YesStandard OAuth 2.0 flow; requires redirect URI
Client CredentialsServer-to-server, unattended integrationsJWT-based (configurable)YesRecommended for daemon/service integrations

XML API Authentication (Session-Based)

FlowUse WhenToken LifetimeRefresh?Notes
Login auth (company credentials)Initial session creation onlySingle requestNoDo NOT use for repeated requests
Session auth (getAPISession)All repeated API calls30 min inactivity timeoutAuto-extends on activityPreferred; returns session ID + unique endpoint

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START -- User needs to integrate with Sage Intacct
|-- Which API surface?
|   |-- Module covered by REST API? (GL, AP, AR, Cash Management, Order Entry)
|   |   |-- YES, and using OAuth 2.0 is acceptable
|   |   |   --> REST API v1 (recommended for new development)
|   |   |-- YES, but need session-based auth or XML batching
|   |       --> XML API DTD 3.0
|   |-- Module NOT covered by REST? (Project Accounting, Fixed Assets, Custom Objects)
|       --> XML API DTD 3.0 (required)
|-- What's the integration pattern?
|   |-- Real-time (< 100 records) --> REST API or XML API single function
|   |-- Batch (< 100 records) --> XML API with transaction="true"
|   |-- Batch (100-1,000 records) --> XML API with chunked batches
|   |-- Batch (> 1,000 records) --> XML API chunked + monitor tier usage
|-- Concurrency needs?
|   |-- <= 2 concurrent --> Default Tier 1
|   |-- > 2 concurrent --> Upgrade performance tier via CSM
|-- Monthly transaction budget?
    |-- < 100,000 --> Tier 1 (included)
    |-- 100,000-2,500,000 --> Tier 2-4 (paid upgrade)
    |-- > 2,500,000 --> Tier 5 (enterprise agreement)

Quick Reference

OperationMethodEndpointPayloadNotes
Create session (XML)POSThttps://api.intacct.com/ia/xml/xmlgw.phtmlXML (getAPISession)Returns sessionid + unique endpoint
Query records (XML)POST{session_endpoint}XML (query)Max 1,000 recommended; paginate with resultId
Create record (XML)POST{session_endpoint}XML (create)Each function = 1 transaction
OAuth token (REST)POSThttps://api.intacct.com/ia/api/v1/oauth2/tokenJSONReturns JWT bearer token
List objects (REST)GEThttps://api.intacct.com/ia/api/v1/objects/{module}/{object}N/ABearer token in Authorization header
Create record (REST)POSThttps://api.intacct.com/ia/api/v1/objects/{module}/{object}JSONBearer token; Content-Type: application/json
Get bank account (REST)GEThttps://api.intacct.com/ia/api/v1/objects/cash-management/bank-account/{key}N/ABearer token

Step-by-Step Integration Guide

1. Obtain Web Services credentials (XML API)

Register as a Sage Intacct developer or obtain a Web Services Developer License. You need: sender ID, sender password, company ID, Web Services user ID, and user password. [src1]

2. Create an API session (XML API)

Use getAPISession to obtain a session ID and unique endpoint. Always isolate getAPISession in its own request. [src1, src2]

<?xml version="1.0" encoding="UTF-8"?>
<request>
  <control>
    <senderid>YOUR_SENDER_ID</senderid>
    <password>YOUR_SENDER_PASSWORD</password>
    <controlid>session-request-1</controlid>
    <uniqueid>false</uniqueid>
    <dtdversion>3.0</dtdversion>
  </control>
  <operation>
    <authentication>
      <login>
        <userid>YOUR_WS_USER_ID</userid>
        <companyid>YOUR_COMPANY_ID</companyid>
        <password>YOUR_WS_USER_PASSWORD</password>
      </login>
    </authentication>
    <content>
      <function controlid="get-session">
        <getAPISession/>
      </function>
    </content>
  </operation>
</request>

Verify: Response contains <sessionid> and <endpoint> elements.

3. Make API calls using session (XML API)

Replace login authentication with the session ID. Send all requests to the unique endpoint returned by getAPISession. [src1]

4. Handle pagination (XML API)

Use readMore with the resultId from previous response to fetch the next page. [src1]

5. Authenticate with OAuth 2.0 (REST API)

Obtain an OAuth 2.0 bearer token from the token endpoint for REST API access. [src3]

curl -X POST "https://api.intacct.com/ia/api/v1/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Verify: Response contains access_token, token_type: "Bearer", and expires_in.

6. Implement error handling and retries

Handle rate limit errors (GW-0010), session timeouts, and mid-process failures with exponential backoff. [src5]

Code Examples

Python: Query AP bills via XML API

# Input:  sender_id, sender_password, session_id, endpoint
# Output: List of AP bill records

import requests
import xml.etree.ElementTree as ET

def query_ap_bills(endpoint, sender_id, sender_pwd, session_id, page_size=100):
    xml_request = f"""<?xml version="1.0" encoding="UTF-8"?>
    <request>
      <control>
        <senderid>{sender_id}</senderid>
        <password>{sender_pwd}</password>
        <controlid>query-bills</controlid>
        <uniqueid>false</uniqueid>
        <dtdversion>3.0</dtdversion>
      </control>
      <operation>
        <authentication>
          <sessionid>{session_id}</sessionid>
        </authentication>
        <content>
          <function controlid="q1">
            <query>
              <object>APBILL</object>
              <select>
                <field>RECORDNO</field>
                <field>VENDORID</field>
                <field>TOTALDUE</field>
              </select>
              <pagesize>{page_size}</pagesize>
            </query>
          </function>
        </content>
      </operation>
    </request>"""
    resp = requests.post(endpoint, data=xml_request,
                         headers={"Content-Type": "application/xml"}, timeout=300)
    root = ET.fromstring(resp.text)
    records = root.findall(".//data/APBILL")
    return [{child.tag: child.text for child in r} for r in records]

JavaScript/Node.js: Create vendor via XML SDK

// Input:  Sage Intacct credentials, vendor data
// Output: Created vendor record number

const IA = require("@sage-intacct/intacct-sdk");

async function createVendor(vendorData) {
  const client = new IA.OnlineClient({
    senderId: process.env.INTACCT_SENDER_ID,
    senderPassword: process.env.INTACCT_SENDER_PASSWORD,
    companyId: process.env.INTACCT_COMPANY_ID,
    userId: process.env.INTACCT_USER_ID,
    userPassword: process.env.INTACCT_USER_PASSWORD,
  });
  const create = new IA.Functions.AccountsPayable.VendorCreate();
  create.vendorId = vendorData.id;
  create.vendorName = vendorData.name;
  const response = await client.execute(create);
  return response.getResults()[0].data;
}

cURL: Quick session creation and query

# Step 1: Create session
curl -s -X POST "https://api.intacct.com/ia/xml/xmlgw.phtml" \
  -H "Content-Type: application/xml" \
  -d '<request>...getAPISession...</request>'
# Extract sessionid and endpoint from response

# Step 2: REST API -- list GL accounts
curl -s "https://api.intacct.com/ia/api/v1/objects/general-ledger/account" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Data Mapping

API Object Mapping (REST to XML)

REST API ObjectXML API ObjectModuleNotes
/objects/general-ledger/accountGLACCOUNTGeneral LedgerFull CRUD both APIs
/objects/general-ledger/journal-entryGLBATCHGeneral LedgerREST uses "journal-entry"; XML uses "GLBATCH"
/objects/accounts-payable/billAPBILLAccounts PayableFull CRUD both APIs
/objects/accounts-payable/vendorVENDORAccounts PayableFull CRUD both APIs
/objects/accounts-receivable/invoiceARINVOICEAccounts ReceivableFull CRUD both APIs
/objects/cash-management/bank-accountBANKACCOUNTCash ManagementREST coverage available
N/APROJECTProject AccountingXML API only
N/AFIXEDASSETFixed AssetsXML API only

Data Type Gotchas

Error Handling & Failure Points

Common Error Codes

CodeMeaningCauseResolution
XL03000003XML Parse schema errorMalformed XML, DTD mismatchValidate XML against DTD 3.0 schema
XL03000006Authentication failureInvalid sender ID or unauthorized senderVerify sender ID is authorized in target company
GW-0010Rate limit / throttlingToo many concurrent requestsImplement exponential backoff; reduce concurrency
GW-0011Invalid requestMalformed gateway requestValidate XML structure; ensure POST method
BL01001973Object not foundReferenced record does not existVerify record exists before create/update
BL34000061Session expired30-minute inactivity timeoutCreate new session via getAPISession
429Too Many RequestsREST API rate limit exceededExponential backoff; respect Retry-After header

Failure Points in Production

Anti-Patterns

Wrong: Using login authentication for every request

<!-- BAD -- creates a new session for every API call, wasting transactions -->
<authentication>
  <login>
    <userid>ws_user</userid>
    <companyid>MYCOMPANY</companyid>
    <password>mypassword</password>
  </login>
</authentication>

Correct: Create session once, reuse for all requests

<!-- GOOD -- one getAPISession, then reuse sessionid -->
<authentication>
  <sessionid>REUSED_SESSION_ID</sessionid>
</authentication>

Wrong: Sending one function per request for bulk operations

# BAD -- 500 separate HTTP requests for 500 vendor creates
for vendor in vendors:
    response = send_xml_request(create_vendor_xml(vendor))

Correct: Batch multiple functions in a single request

# GOOD -- one HTTP request with multiple functions
functions_xml = "".join([create_vendor_xml(v) for v in vendors[:100]])
request_xml = wrap_in_operation(functions_xml, transaction=True)
response = send_xml_request(request_xml)

Wrong: Ignoring the unique session endpoint

# BAD -- always sending to the generic gateway
SESSION_ENDPOINT = "https://api.intacct.com/ia/xml/xmlgw.phtml"

Correct: Use the endpoint returned by getAPISession

# GOOD -- use the session-specific endpoint
session_info = create_session()
SESSION_ENDPOINT = session_info["endpoint"]  # e.g., https://na12.intacct.com/...

Common Pitfalls

Diagnostic Commands

# Test XML API authentication -- create session
curl -s -X POST "https://api.intacct.com/ia/xml/xmlgw.phtml" \
  -H "Content-Type: application/xml" \
  -d '<request><control>...</control><operation>...getAPISession...</operation></request>'
# Expected: <status>success</status> with sessionid and endpoint

# Test REST API authentication -- get token
curl -s -X POST "https://api.intacct.com/ia/api/v1/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=YOUR_ID&client_secret=YOUR_SECRET"

# Test REST API -- list GL accounts
curl -s "https://api.intacct.com/ia/api/v1/objects/general-ledger/account" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Check API usage: Company > Admin > Usage Insights > API Usage (UI only)

Version History & Compatibility

API VersionRelease DateStatusBreaking ChangesMigration Notes
REST API v12023Current (expanding)N/A -- additive onlyNew modules added quarterly (R1-R4)
XML DTD 3.02018+Current (maintenance)None recentFull feature coverage; recommended for XML
XML DTD 2.1Pre-2018Legacy (supported)No new featuresMigrate to DTD 3.0
HTTP GET blocking2023-01-15EnforcedGET requests rejectedUse POST for all XML API calls
REST API 2025 R42025-12CurrentNew objects addedCheck release notes

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
New GL, AP, AR, or cash management integrationsNeed project accounting, fixed assets, or custom objectsXML API DTD 3.0 for unsupported modules
Mid-market financial management with <100K API calls/monthHigh-volume processing (>250K calls/month) without budget for premium tiersiPaaS with batch optimization or Tier 2+ upgrade
OAuth 2.0 is your standard auth pattern (REST API)Platform only supports session-based auth nativelyXML API with getAPISession
Simple JSON payloads for standard financial recordsComplex multi-step transactions with rollbackXML API with transaction="true"

Important Caveats

Related Units