Advanced Intercompany Journal Entries are one of the more nuanced record types in NetSuite. Creating them through the UI is well documented. Creating them through the REST API is not.
The biggest risk isn't getting an error. It's getting a successful save that silently skips the intercompany pairing because a field name was wrong. That kind of failure doesn't surface until period close, which is exactly when you don't want to discover it.
Here's how to do it correctly, with explicit callouts on what to verify before deploying.
Prerequisites
Before you write any code, confirm these features are enabled:
- NetSuite OneWorld. Intercompany journals are a OneWorld feature.
- Advanced Intercompany Journal Entries. Enable under Setup → Accounting → Accounting Preferences → General tab.
- REST Web Services. Enable under Setup → Company → Enable Features → SuiteCloud tab.
- Token-Based Authentication (TBA) or OAuth 2.0. Same location, SuiteCloud tab.
Your role also needs Journal Entries (Create/Edit), Intercompany Journal Entries (Create/Edit), and REST Web Services permissions.
The Endpoint
AICJEs use the advintercompanyjournalentry record type in the REST Record API:
POST https://{accountId}.suitetalk.api.netsuite.com/services/rest/record/v1/advintercompanyjournalentry
Verify this. Confirm the exact record type string in the NetSuite Records Browser for your account's API version. Record type strings are case-sensitive.
Authentication
Two options, depending on your setup:
Token-Based Authentication:
Authorization: NLAuth nlauth_account={accountId},
nlauth_email={email},
nlauth_signature={token},
nlauth_role={roleId}
OAuth 2.0 Bearer Token:
Authorization: Bearer {access_token}
Request Structure
Here's the JSON body for a simple 2-line AICJE where Subsidiary 1 charges Subsidiary 2 a $5,000 management fee:
{
"subsidiary": {
"id": "1"
},
"trandate": "2026-01-08",
"currency": {
"id": "1"
},
"memo": "Intercompany charge - Q1 management fee",
"line": {
"items": [
{
"account": { "id": "101" },
"debit": 5000.00,
"memo": "Management fee charge",
"subsidiary": { "id": "1" },
"duetosubsidiary": { "id": "2" }
},
{
"account": { "id": "201" },
"credit": 5000.00,
"memo": "Management fee payable",
"subsidiary": { "id": "2" },
"duefromsubsidiary": { "id": "1" }
}
]
}
}
A critical note on the field names: duetosubsidiary, duefromsubsidiary, and linesubsidiary are my best representation based on SuiteScript/SuiteQL naming conventions. Confirm the exact REST field names in the Records Browser under the advintercompanyjournalentry record's line sublist before using these in production. A wrong field name will silently fail to set the intercompany pairing rather than returning an error.
How Due To / Due From Works
The intercompany pairing logic works at the line level. Each line that crosses subsidiary boundaries must specify which subsidiary owns the line and which subsidiary the amount is due to or due from.
In the example above:
- Line 1 sits on Subsidiary 1's books. It debits a revenue account and indicates the amount is due to Subsidiary 2.
- Line 2 sits on Subsidiary 2's books. It credits an expense account and indicates the amount is due from Subsidiary 1.
The AICJE captures both sides in a single journal. NetSuite handles the elimination entries when you consolidate.
Full Working Example
const response = await fetch(
"https://{accountId}.suitetalk.api.netsuite.com/services/rest/record/v1/advintercompanyjournalentry",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "NLAuth nlauth_account={accountId},nlauth_email={email},nlauth_signature={token},nlauth_role={roleId}"
},
body: JSON.stringify({
subsidiary: { id: "1" },
trandate: "2026-01-08",
currency: { id: "1" },
memo: "Q1 Management Fee - Sub 1 to Sub 2",
line: {
items: [
{
account: { id: "101" }, // VERIFY: your revenue account internal ID
debit: 5000.00,
memo: "Management fee revenue",
subsidiary: { id: "1" },
duetosubsidiary: { id: "2" } // VERIFY: exact field name
},
{
account: { id: "201" }, // VERIFY: your expense account internal ID
credit: 5000.00,
memo: "Management fee expense",
subsidiary: { id: "2" },
duefromsubsidiary: { id: "1" } // VERIFY: exact field name
}
]
}
})
}
);
const data = await response.json();
if (!response.ok) {
console.error("Error creating AICJE:", JSON.stringify(data, null, 2));
} else {
console.log("AICJE created. Internal ID:", data.id);
}
Looking Up Internal IDs
You'll need account, subsidiary, and currency internal IDs. The REST API makes this straightforward:
GET /services/rest/record/v1/account?q=name CONTAINS "Management Fee"
GET /services/rest/record/v1/subsidiary
GET /services/rest/record/v1/currency
Common Errors
A few patterns to watch for:
- INVALID_RECORD_TYPE. The record type string is wrong. Verify
advintercompanyjournalentryin the Records Browser. - INVALID_FLD_VALUE on line fields. A field name is wrong or the internal ID doesn't exist.
- INSUFFICIENT_PERMISSION. The role is missing Intercompany Journal Entry or REST Web Services permissions.
- REQUIRED_FEATURE_UNAVAILABLE. The Advanced Intercompany Journal Entries feature isn't enabled.
- Lines post but no intercompany pairing. This is the dangerous one. It means the due to/due from field names are wrong. The journal saves, but the pairing is silently skipped. You won't notice until consolidation.
Verify Before Production
This is not a record type you want to deploy without thorough sandbox testing. Here's the sequence:
- Records Browser first. Look up
advintercompanyjournalentry→linesublist. Confirm the exact REST field names for due to/due from subsidiary fields. - POST to sandbox with a simple 2-line entry.
- Retrieve the record after creation and inspect the line sublist to confirm the pairing fields are populated:
GET /services/rest/record/v1/advintercompanyjournalentry/{id}?expandSubResources=true - Check the journal in the UI. Open the created AICJE and confirm the Due To/Due From columns on the line sublist are populated correctly.
- Run elimination in a sandbox accounting period to confirm the intercompany entries eliminate correctly.
The verification steps matter more here than with most record types. A standard journal entry with a wrong field will usually throw an error. An AICJE with wrong intercompany fields will save cleanly and create a problem you won't find until you need your consolidated financials to be right.