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:

Copy
Copied
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:

Copy
Copied
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
Copy
Copied
{
    "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:

Copy
Copied
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:

Copy
Copied
{
    "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:

Copy
Copied
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:

Copy
Copied
--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.

Copy
Copied
{
    "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.

Copy
Copied
{
    "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):

Copy
Copied
DELETE 'https://api.intacct.com/api/v1/objects/company-config/contact/719,7513' \
Copy
Copied
{
    "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:

Copy
Copied
PATCH `https://api.intacct.com/api/v1/objects/order-entry/document-line::Sales Credit Memo
Copy
Copied
[
    {
        "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
    Copy
    Copied
    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:

Copy
Copied
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 as accounts-payable/vendor .
  • operation : must be create for a POST, update for a PATCH, or delete for a DELETE operation.
  • jobFile : the name of your file input.
  • fileContentType : the format of your file, must be json .
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:

Copy
Copied
[
 {"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:

Copy
Copied
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:

Copy
Copied
[
    { "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:

Copy
Copied
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:

Copy
Copied
[
    { "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
    Copy
    Copied
    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:

Copy
Copied
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 and Accept 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:

Copy
Copied
  https:///api.intacct.com/ia/api/{version}/services/core/composite

Sample request body

Copy
Copied
[
    {
      "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

Copy
Copied
{
    "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

Copy
Copied
{
    "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):

Copy
Copied
--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 and query 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.