ERP → Salesforce¶
ERP calls Salesforce only when the local row already has a Salesforce Id. The Id is the one stored by the onboarding callback. Auth is the same OAuth client credentials as onboarding. The base path is /services/data/v67.0.
If the Salesforce call fails, the ERP row is already saved. The ERP HTTP response is still success. The failure is on the integration log, and a later POST /api/accounts/sold-tos/DIST001/sync-to-salesforce (or the Bill To equivalent) sends it again.
PATCH /sobjects/Account/001000000000001AAA¶
Update the Sold To. This example changes the street, the pincode, the payment terms, and fills the bank fields that onboarding did not send.
What the ERP API receives¶
PATCH /api/accounts/sold-tos/DIST001
{
"name": "Sharma Distributors",
"gstRegistrationNumber": "29ABCDE1234F1Z5",
"panNumber": "ABCDE1234F",
"billingAddress": {
"street": "15 Brigade Road",
"city": "Bengaluru",
"state": "Karnataka",
"pincode": "560001"
},
"bankAccountName": "Sharma Distributors",
"bankAccountNumber": "50100234567890",
"bankIfscCode": "HDFC0001234",
"paymentTerms": "Net 45",
"territoryCode": "TER-KA-BLR-01"
}
ERP answers HTTP 200 with the saved Sold To, including "salesforceRecordId": "001000000000001AAA" and "paymentTerms": "Net 45".
What ERP sends to Salesforce¶
PATCH /services/data/v67.0/sobjects/Account/001000000000001AAA
Authorization: Bearer {access token}
Content-Type: application/json
{
"Name": "Sharma Distributors",
"GST_Registration_Number__c": "29ABCDE1234F1Z5",
"PAN_Number__c": "ABCDE1234F",
"Bank_Account_Name__c": "Sharma Distributors",
"Bank_Account_Number__c": "50100234567890",
"Bank_IFSC_Code__c": "HDFC0001234",
"BillingStreet": "15 Brigade Road",
"BillingCity": "Bengaluru",
"BillingState": "Karnataka",
"BillingPostalCode": "560001",
"BillingCountry": "India",
"Payment_Terms__c": "Net 45",
"Territory__r": {
"Territory_Code__c": "TER-KA-BLR-01"
}
}
Sold_To_Code__c, record type, and Account_Status__c are not on this body. Empty bank fields are omitted. BillingCountry is always India.
Salesforce answers HTTP 204 with an empty body. See Salesforce → ERP.
PATCH /sobjects/Account/001000000000002AAA¶
Update the Bill To. The ERP API accepts only the name and the address.
What the ERP API receives¶
PATCH /api/accounts/bill-tos/BILL001
{
"name": "Sharma Distributors - Billing",
"billingAddress": {
"street": "15 Brigade Road",
"city": "Bengaluru",
"state": "Karnataka",
"pincode": "560001"
}
}
What ERP sends to Salesforce¶
{
"Name": "Sharma Distributors - Billing",
"GST_Registration_Number__c": "29ABCDE1234F1Z5",
"BillingStreet": "15 Brigade Road",
"BillingCity": "Bengaluru",
"BillingState": "Karnataka",
"BillingPostalCode": "560001",
"BillingCountry": "India",
"ERP_Sync_Status__c": "Synced",
"ERP_Last_Sync_Timestamp__c": "2026-11-06T04:00:00Z"
}
GST is copied from Sold To DIST001. It is not a field on the ERP update body. Bill_To_Code__c and Parent are not sent again.
Salesforce answers HTTP 204.
POST /sobjects/Account¶
Add a second Bill To under DIST001. The parent Sold To must already have a Salesforce Id, and it must not be inactive.
What the ERP API receives¶
POST /api/accounts/sold-tos/DIST001/bill-tos
{
"name": "Whitefield Warehouse",
"billingAddress": {
"street": "Plot 7, EPIP Zone",
"city": "Bengaluru",
"state": "Karnataka",
"pincode": "560066"
}
}
ERP assigns the code from the name. The last significant word is Warehouse, so the code is WARE001 when no earlier WARE code exists. ERP answers HTTP 201:
What ERP sends to Salesforce¶
The parent link is ParentId, because the Sold To Salesforce Id is already known. GST is copied from DIST001.
POST /services/data/v67.0/sobjects/Account
Authorization: Bearer {access token}
Content-Type: application/json
Sforce-Duplicate-Rule-Header: allowSave=true
{
"RecordTypeId": "012000000000002AAA",
"Name": "Whitefield Warehouse",
"Bill_To_Code__c": "WARE001",
"ParentId": "001000000000001AAA",
"GST_Registration_Number__c": "29ABCDE1234F1Z5",
"BillingStreet": "Plot 7, EPIP Zone",
"BillingCity": "Bengaluru",
"BillingState": "Karnataka",
"BillingPostalCode": "560066",
"BillingCountry": "India",
"Account_Status__c": "Active",
"ERP_Sync_Status__c": "Synced",
"ERP_Last_Sync_Timestamp__c": "2026-11-06T04:00:00Z",
"ERP_Record_ID__c": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
}
RecordTypeId is the org's Bill To record type. ERP_Record_ID__c is ERP's row id for WARE001.
Salesforce answers HTTP 201:
ERP stores 001000000000003AAA on WARE001 from this body. The insert also makes Salesforce send the record-id callback. A repeat of the same Id is accepted.
PATCH Account_Status__c¶
One status body covers freeze, unfreeze, deactivate, and activate. Only Account_Status__c changes. ERP does not send a separate call for each child Bill To.
Freeze DIST001¶
ERP API: PATCH /api/accounts/sold-tos/DIST001/freeze. No body.
ERP sets DIST001 to Frozen. Every Active child Bill To, including BILL001, becomes Inactive in ERP and is flagged inactivated_by_parent_freeze. A Bill To that was already inactive on its own is left as it is.
ERP sends only:
{
"Account_Status__c": "Frozen",
"ERP_Sync_Status__c": "Synced",
"ERP_Last_Sync_Timestamp__c": "2026-11-06T04:10:00Z"
}
Salesforce's SoldTo_AfterSave then sets each Active child Bill To to Inactive and stamps Inactivated_By_Parent_Freeze__c. ERP's HTTP answer is:
Freezing BILL001 alone is PATCH /api/accounts/bill-tos/BILL001/freeze. That Bill To becomes Frozen in ERP, and the Salesforce body uses "Account_Status__c": "Frozen" on 001000000000002AAA. Sibling Bill Tos are not touched. This is a different outcome from a Sold To freeze, which makes the children Inactive rather than Frozen.
Unfreeze DIST001¶
ERP API: PATCH /api/accounts/sold-tos/DIST001/unfreeze. The Sold To must be Frozen.
DIST001 returns to Active. Only Bill Tos flagged by the freeze return to Active. A Bill To deactivated on its own stays Inactive.
{
"Account_Status__c": "Active",
"ERP_Sync_Status__c": "Synced",
"ERP_Last_Sync_Timestamp__c": "2026-11-06T04:20:00Z"
}
Salesforce restores the flagged child Bill Tos to Active. ERP answers "status": "Active".
Deactivate DIST001¶
ERP API: PATCH /api/accounts/sold-tos/DIST001/deactivate.
DIST001 and every child Bill To become Inactive in ERP. The freeze flag on those Bill Tos is cleared. ERP sends one PATCH, with "Account_Status__c": "Inactive", to 001000000000001AAA.
SoldTo_AfterSave sets every child Bill To to Inactive, clears Inactivated_By_Parent_Freeze__c, and sets Stock_Norm__c.Is_Active__c to false for that Sold To.
Deactivating only BILL001 sends "Account_Status__c": "Inactive" to 001000000000002AAA. DIST001 stays Active.
Activate¶
PATCH /api/accounts/sold-tos/DIST001/activate and PATCH /api/accounts/bill-tos/BILL001/activate are only valid when that one account is Inactive.
The Salesforce body is the same Active payload as unfreeze. Child Bill Tos are not turned back on. Each one needs its own activate call. Activating the Sold To does not send a PATCH for BILL001.