Batch, bulk, and composite requests
To increase the performance of your application, use batch, bulk, or composite requests to combine multiple REST API requests into a single request.
Batch requests
You can process multiple records (batch) for a single REST API object in one request. For example, you can retrieve bills with key
set to 194, 195, 310, and 145 with the following request:
GET https://api.intacct.com/ia/api/{version}/objects/accounts-payable/bill/194,195,310,145
You can include at most 500 records in a batch request.
Examples
POST
Include the records you want to create in the body of the POST request, which is structured as an array of objects. You can use the following request to create three company-config/contact
records:
curl --location --request POST 'https://api.intacct.com/ia/api/{version}/objects/company-config/contact' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'Cookie: DFT_LOCALE=en_US.UTF-8 \
--data-raw '[
{
"id": "CYoung",
"email1": "[email protected]",
"email2": "[email protected]",
"printAs": "Caroline Young"
},
{
"id": "FYoung",
"email1": "[email protected]",
"email2": "[email protected]",
"printAs": "Fred Young"
},
{
"id": "WYoung",
"email1": "[email protected]",
"email2": "[email protected]",
"printAs": "Wes Young"
}
]'
The response contains:
-
ia::result
- an array of references to the objects that were created -
ia::meta
- summary of the overall response status
{
"ia::result": [
{
"key": "1",
"id": "CYoung",
"href": "/objects/company-config/contact/1"
},
{
"key": "2",
"id": "FYoung",
"href": "/objects/company-config/contact/2"
},
{
"key": "3",
"id": "WYoung",
"href": "/objects/company-config/contact/3"
}
],
"ia::meta": {
"totalCount": 3,
"totalSuccess": 3,
"totalError": 0
}
}
PATCH
Unlike for individual REST API requests, specify the object key
in the request body, not in the path. You can use the following request to modify company-config/contact
records:
curl --location --request PATCH 'https://api.intacct.com/ai/api/{version}/objects/company-config/contact' \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--header 'Cookie: DFT_LOCALE=en_US.UTF-8 \
--data-raw '[
{
"key": "1",
"email1": "[email protected]",
"email2": "[email protected]"
},
{
"key": "2",
"email1": "[email protected]",
"email2": "[email protected]"
}
]'
Sample response:
{
"ia::result": [
{
"key": "1",
"id": "1",
"href": "/objects/company-config/contact/1"
},
{
"key": "2",
"id": "2",
"href": "/objects/company-config/contact/2"
}
],
"ia::meta": {
"totalCount": 2,
"totalSuccess": 2,
"totalError": 0
}
}
DELETE
You can use the following request to delete three company-config/contact
records:
DELETE https://api.intacct.com/ai/api/{version}/objects/company-config/contact/1,2,3
A successful response returns HTTP status 204 No Content
and an empty payload.
Atomic requests
You can configure REST API batch requests to be processed atomically or non-atomically. In atomic mode, if any operation within a transaction fails, the entire transaction is rolled back and the data is left in its original state. Note that atomic batch requests are called "transactions" in the Intacct XML API.
Multiple records of owned objects (such as
accounts-payable/bill-line
) specified in one request are processed in one atomic transaction when the request is made via the owning object (accounts-payable/bill
). This is not considered to be a batch request. See Owner and owned objects for details.
To configure a batch request to handle all records in a request atomically, include the following header in your request:
--header 'X-IA-API-Param-Transaction: true'
When the atomic mode is enabled, the entire request is aborted with some individual requests rolled back or skipped due to a single failure. The REST API returns a 207 Multi-Status
, 404 Not Found
, 422 Unprocessable Entity
, or another HTTP error according to the problem encountered. Each individual response (ia::result
) contains its request status (ia::status
) and error (ia::error
) information, and the overall status is summarized in the ia::meta
property.
{
"ia::result": [
{
"ia::status": 422,
"ia::error": {
"code": "atomicOperationFailure",
"message": "Operation skipped due to atomic transaction failure",
"errorId": "REST-7012",
"additionalInfo": {
"messageId": "IA.OPERATION_SKIPPED_DUE_TO_ATOMIC_TRANSACTION_FAILURE",
"placeholders": {},
"propertySet": {}
},
"supportId": "jka0NWEB030%7EZ920qP3o0nQ8Ne8-rQ-0NgAAAAA"
}
},
{
"key": "25999",
"href": "/objects/company-config/contact/25999",
"ia::status": 404,
"ia::error": {
"code": "notFound",
"message": "objects/company-config/contact 25999 could not be found",
"errorId": "REST-4001",
"additionalInfo": {
"messageId": "IA.OBJECT_COULD_NOT_BE_FOUND",
"placeholders": {
"OBJECT": "objects/company-config/contact",
"RECORD_NO": "25999"
},
"propertySet": {}
},
"supportId": "jka0NWEB030%7EZ920qP3o0nQ8Ne8-rQ-0NgAAAAA"
}
}
],
"ia::meta": {
"totalCount": 2,
"totalSuccess": 0,
"totalError": 2
}
}
Non-atomic requests
By default, batch requests are non-atomic. When a non-atomic request is unsuccessful or partially successful, each individual response contains its request status, and the overall status is summarized in the ia::meta
property.
{
"ia::result": [
{
"key": "249",
"id": "Krishna",
"href": "/objects/company-config/contact/249",
"ia::status": 200
},
{
"key": "25999",
"href": "/objects/company-config/contact/25999",
"ia::status": 404,
"ia::error": {
"code": "notFound",
"message": "objects/company-config/contact 25999 could not be found",
"errorId": "REST-4001",
"additionalInfo": {
"messageId": "IA.OBJECT_COULD_NOT_BE_FOUND",
"placeholders": {
"OBJECT": "objects/company-config/contact",
"RECORD_NO": "25999"
},
"propertySet": {}
},
"supportId": "skCLrWEB030%7EZ93S8P330pM8ntP-kIM25QAAAAY"
}
}
],
"ia::meta": {
"totalCount": 2,
"totalSuccess": 1,
"totalError": 1
}
}
For a partially successful DELETE request, the key
property is not included in the individual responses that were successful. You can correlate the successful response with the request according to its position (index) in the array. In the following example, the first record failed to be deleted ("key": "719", "ia::status": 422
), and the second record (7513) was successfully deleted ("ia::status": 204
):
DELETE 'https://api.intacct.com/api/v1/objects/company-config/contact/719,7513' \
{
"ia::result": [
{
"key": "719",
"href": "/objects/company-config/contact/719",
"ia::status": 422,
"ia::error": {
"code": "operationFailed",
"message": "DELETE request on objects/company-config/contact object was unsuccessful",
"errorId": "REST-7001",
"additionalInfo": {
"messageId": "IA.REQUEST_ON_OBJECT_FAILED",
"placeholders": {
"OPERATION": "DELETE",
"RESOURCE_NAME": "objects/company-config/contact"
},
"propertySet": {}
},
"supportId": "s9tZLWEB030%7EZ-YobP3o0wn8AjN-4dfCnAAAAAc",
"details": [
{
"errorId": "CO-0137",
"code": "invalidConfiguration",
"message": "Could not delete Contact record 'vsoe_ven_cont_033_R'",
"additionalInfo": {
"messageId": "IA.COULD_NOT_DELETE_CONTACT_RECORD_NAME",
"placeholders": {
"NAME": "vsoe_ven_cont_033_R"
},
"propertySet": {}
}
},
{
"errorId": "CORE-1305",
"code": "invalidRequest",
"message": "Another area of the system references this object. Remove or change the reference in that record before deleting the object. The record is used in one of the following: Supplier,Supplier visibility",
"correction": "Delete the dependent records and try again.",
"additionalInfo": {
"messageId": "IA.ANOTHER_AREA_OF_THE_SYSTEM_REFERENCES_THIS_OBJE",
"placeholders": {},
"propertySet": {}
}
}
]
}
},
{
"ia::status": 204
}
],
"ia::meta": {
"totalCount": 2,
"totalSuccess": 1,
"totalError": 1
}
}
Batch requests on owned objects
You can include owned objects in your batch requests. See Owner and owned objects for information about owned objects and mixed operation requests.
You must include the key of the owning object for each record in the request. For example, the following requests performs operations on lines of the order-entry/document-line
objects with key
of 66
and 67
:
PATCH `https://api.intacct.com/api/v1/objects/order-entry/document-line::Sales Credit Memo
[
{
"key": "66",
"lines": [
{
"memo": "Doc A,ln 3",
"unitQuantity": "1",
"dimensions": {
"location": {
"key": "1"
},
"warehouse": {
"key": "1"
}
}
},
{
"key": "77",
"memo": "mixed-op",
"unitQuantity": "1",
"ia::operation": "delete"
}
]
},
{
"key": "67",
"lines": [
{
"key": "80",
"memo": "mixed-op",
"ia::operation": "delete"
},
{
"key": "79",
"memo": "mixed-op",
"unitQuantity": "1",
"ia::operation": "patch"
}
]
}
]
Bulk requests
Use the bulk request service to process multiple operations for one REST object with a single HTTPS call. The service provides two functions: file upload to submit a bulk request for asynchronous processing, and job status to get the status of asynchronous jobs.
See the Send a bulk request and Get a bulk request status reference pages for a list and description of fields you can include in bulk requests.
Submit a bulk request
Creating a new bulk API request involves specifying the object type and operation in the request body and uploading a file, which contains the data for your objects. Operations are processed as separate transactions. Processing proceeds to the next operation on success or failure.
Data is passed into the request via a JSON file.
Currently, there is no limit on the number of operations in a bulk request.
The service uploads the file, records the job details and the callback URL, and returns a job ID. You can use the job ID to get the status and the detailed report of the job, see the Check the bulk request status section for details.
Bulk request URI and examples
-
URI
https://api.intacct.com/ia/api/{version}/services/bulk/job/create
- HTTP method : POST
For example, use the following cURL command to submit a bulk request to create accounts-payable/vendor
objects:
curl --location 'https://api.intacct.com/ia/api/v1/services/bulk/job/create' \
--header 'Authorization: Bearer {{your_authorization_token}}' \
--header 'Cookie: DFT_LOCALE=en_US.UTF-8' \
--form 'ia::requestBody="{ \"objectName\" : \"accounts-payable/vendor\", \"operation\": \"create\", \"jobFile\" : \"file\", \"fileContentType\" : \"json\"}";type=application/json' \
--form 'file=@"/Users/firstname.lastname/Desktop/BULK Files/vendors.json"'
ia::requestBody
Pass the following attributes in the request body, with each value in double quotes:
-
objectName
: the REST object targeted by the request, such asaccounts-payable/vendor
. -
operation
: must becreate
for a POST,update
for a PATCH, ordelete
for a DELETE operation. -
jobFile
: the name of yourfile
input. -
fileContentType
: the format of your file, must bejson
.
file
The contents of your file must represent the objects to be created, updated, or deleted, in JSON format.
The object properties specified in your file must match the schema definition of the object. If there is a mismatch, the object will not be created. Processing will proceed and an error entry will be recorded for each failed transaction.
The following example shows a file with three accounts-payable/vendor
objects:
[
{"id":"vendor1","name":"Corner Library","billingType":null,"term":{"key":"8"},"vendorType":{"key":"1"},"accountGroup":{"key":"1"}},
{"id":"vendor2","name":"Just Picked","billingType":null,"term":{"key":"8"},"vendorType":{"key":"1"},"accountGroup":{"key":"1"}},
{"id":"vendor3","name":"Petco","billingType":null,"term":{"key":"8"},"vendorType":{"key":"1"},"accountGroup":{"key":"1"}},
]
Additional examples
Bulk update request
Use the following cURL command to submit a bulk request to update general-ledger.journal-entry
objects:
curl --location 'https://api.intacct.com/ia/api/v1/services/bulk/job/create' \
--header 'Authorization: Bearer {{your_authorization_token}}' \
--header 'Cookie: DFT_LOCALE=en_US.UTF-8' \
--form 'ia::requestBody="{ \"objectName\" : \"general-ledger/journal-entry\", \"operation\": \"update\", \"jobFile\": \"test\", \"fileContentType\" : \"json\", \"callbackURL\": \"\"}";type=application/json' \
--form 'test=@"/Users/firstname.lastname/Desktop/JE/PATCH_JE.json"'
The following example shows a file with updates to general-ledger.journal-entry
objects:
[
{ "key": "48601", "description": "yesterday" },
{ "key": "48602", "description": "today" },
{ "key": "60171", "description": "tomorrow" }
]
Bulk delete request
Use the following cURL command to submit a bulk request to delete general-ledger.journal-entry
objects:
curl --location 'https://api.intacct.com/ia/api/v1/services/bulk/job/create' \
--header 'Authorization: Bearer {{your_authorization_token}}' \
--header 'Cookie: DFT_LOCALE=en_US.UTF-8' \
--form 'ia::requestBody="{ \"objectName\" : \"general-ledger/journal-entry\", \"operation\": \"delete\", \"jobFile\": \"test\", \"fileContentType\" : \"json\", \"callbackURL\": \"\"}";type=application/json' \
--form 'test=@"/Users/firstname.lastname/Desktop/BULK/DELETE_small.json"'
The following example shows a file with the general-ledger.journal-entry
objects to be deleted:
[
{ "key": "31097" },
{ "key": "31098" },
{ "key": "31099" }
]
Check the bulk request status
After the bulk request has been sent, you can monitor the status of the job.
Job status request URI and examples
-
URI
https://api.intacct.com/ia/api/{version}/services/bulk/job/status
- HTTP method : GET
For example, use the following cURL command to send a status request for a specified job ID:
curl --location 'https://api.intacct.com/ia/api/v1/services/bulk/job/status?jobId={{job_id}}&download=true' \
--header 'Authorization: Bearer {{your_authorization_token}}' \
--header 'Content-Type: application/json' \
--header 'Cookie: DFT_LOCALE=en_US.UTF-8'
The request returns the status of the job, which can be: queued
, processing
, completed
, or failed
. Once the job is completed, set the optional boolean download
parameter to true
to download the results of all the operations in JSON format. If the download
parameter is omitted or is set to false
, only the job status is returned.
Composite requests
Use the composite request service to send a request containing multiple sub-requests for different objects or services in a single HTTPS call. For example, you can create a new contact, update an existing vendor, query bills, and so forth, in a single request.
The composite request service is designed to:
- Support mixed operations, for example GET and POST.
-
Support a combination of operations and services in one request. Each sub-request path is restricted to
/objects/...
or/services/...
. - Support operations on different objects in one request.
- Use the output from one sub-request in subsequent sub-requests. For example, you can save the key of the newly created object and use it in subsequent sub-requests.
-
Support HTTP request and response headers for each sub-request.
Authorization
,Content-Type
andAccept
headers cannot be specified for each sub-request, they are inherited from the top level.
The composite service supports between 2 and 10 sub-requests. Permissions are checked for each sub-request during execution.
All sub-requests must use the same version of the API as the composite request. You cannot use a combination of API versions.
Sub-requests are executed sequentially. The execution stops on first failure with no rollback of any previous sub-requests.
Composite request responses are synchronous.
Composite request URI and examples
See the Send a composite request reference page for a list and description of fields you can include in a composite request. Send the request to the following endpoint URL using the POST method:
https:///api.intacct.com/ia/api/{version}/services/core/composite
Sample request body
[
{
"method": "POST",
"path": "/objects/accounts-payable/vendor",
"body": { ... },
"resultReference": "vendor",
"headers": {
"X-ABC": "123"
}
},
{
"method": "GET",
"path": "/objects/accounts-payable/vendor/@{vendor.1.key}"
}
]
Sample response body - success
{
"ia::result": [
{
"ia::result": [{ ... }],
"ia::meta": {
"totalCount": 1
},
"ia::status": 200,
"ia::headers": {
"X-ORM-ACTION": "create"
}
},
{
"ia::result": [{ ... }],
"ia::meta": {
"totalCount": 1
},
"ia::status": 200
}
],
"ia::meta": {
"totalCount": 2,
"totalSuccess": 2,
"totalError": 0
}
}
Sample response body - failure
{
"ia::result": [
{
"ia::error": [{ ... }],
"ia::meta": {
"totalCount": 1
},
"ia::status": 400
},
{
"ia::error": [{ <message that the request was not processed> }],
"ia::meta": {
"totalCount": 1
},
"ia::status": 422
}
],
"ia::meta": {
"totalCount": 2,
"totalSuccess": 0,
"totalError": 2
}
}
Preventing duplicate requests
You can use the Idempotency-Key
header to prevent duplicate POST
and PATCH
requests from being processed by Sage Intacct. (GET
and DELETE
requests are already idempotent and do not support the use of this header.)
To enable idempotency for a request, include the following header with a unique value such as a UUID (max 256 characters):
--header 'Idempotency-Key: e9606bb2-6be1-4c9e-a2a7-134cd644a5ee'
Intacct duplicate request prevention includes:
- Intacct saves the idempotency key, the original request, and the response, even if the request fails.
-
The
Idempotency-Key
header and value is included in the response. -
The response includes an additional header containing the date and time the original request was processed:
x-ia-idempotency-cached-date: 2025-04-01T19:54:51+0000
- Once the request has been completed, Intacct caches the result for 48 hours. If a duplicate request with the same idempotency key, payload, and credential is received, Intacct returns the original status and the cached results.
- Reusing a key with a different request body returns a 409 (Conflict) error.
- Intacct stores the idempotency key for 60 days (including the first 48 hours) and returns a 409 status if a request is received with the same key during that time.
Additional notes:
-
Core services such as
model
andquery
do not support idempotency. - If multiple identical requests are received before the first one has finished processing, the first one will receive the idempotency lock and the others will return an error.