[SalesForce] How to Upsert Multiple childs with SOAP or REST API

I have an opportunity and child objects customobj1 and customobj2. I need to update the opportunity and upsert the child objects customobj1 and customobj2. It seems there is a limitation where we cannot update/usert multiple objects in a soap api upsert call according to salesforce documentation here.
I have also tried to use the REST API but did not find a way to update it. This is json I have used with patch

      {
    "records" :[{
    "attributes" : {"type" : "Account", "referenceId" : "ref1"},
    "name" : "SampleAccount",
    "phone" : "1234567890",
    "website" : "www.salesforce.com",
    "id"       : "0016300000NOteE",
    "numberOfEmployees" : "100",
    "type" : "Analyst",
    "industry" : "Banking",
    "Contacts" : {
      "records" : [{
         "attributes" : {"type" : "Contact", "referenceId" : "ref2"},
         "lastname" : "Smith",
         "title" : "President",
         "email" : "sample@salesforce.com"
         },{         
         "attributes" : {"type" : "Contact", "referenceId" : "ref3"},
         "lastname" : "Evans",
         "title" : "Vice President",
         "email" : "sample@salesforce.com"
         }]
      },
    "Opportunities" : {
      "records" : [{
         "attributes" : {"type" : "Opportunity", "referenceId" : "ref4"},
         "Name" : "Test Opty",
         "StageName" : "Prospecting",
         "CloseDate" : "2018-03-19"
         }]
      }
    }]
}

I have updated code as suggested by Daniel like this

 {
    "allOrNone" : true,
    "compositeRequest" : [{
        "method" : "PATCH",
        "url" : "/services/data/v39.0/sobjects/Account/001i000002CPZlD",
        "referenceId" : "UpdatedAccount",
        "body" : {  
            "Name" : "SampleAccount",
            "Phone" : "7702345678"
        }
    },{
        "method" : "PATCH",
        "referenceId" : "NewContact",
        "url" : "/services/data/v39.0/sobjects/Contact/",
        "body" : {  
            "lastname" : "Smithchanged",
            "title" : "President",
            "email" : "sample@salesforce.com",
            "con_ext_id__c" : "c222",
            "AccountId" : "001i000002CPZlD"
        }
    },{
        "method" : "PATCH",
        "referenceId" : "NewContact2",
        "url" : "/services/data/v39.0/sobjects/Contact/",
        "body" : {  
            "lastname" : "Evanschanged",
            "title" : "Vice President",
            "email" : "sample@salesforce.com",
            "con_ext_id__c" : "c111",
            "AccountId" : "001i000002CPZlD"
        }
    },{
        "method" : "PATCH",
        "referenceId" : "opportunity1",
        "url" : "/services/data/v38.0/sobjects/opportunity",
        "body" : {  
            "Name" : "Test Optyone Changed",
            "StageName" : "Prospecting",
            "CloseDate" : "2018-03-19",
            "opty_ext_id__c" : "123",
            "AccountId" : "001i000002CPZlD"
        }
    }]
}

I have received following error message for child objects as errorCode: METHOD_NOT_ALLOWED
message: HTTP Method 'PATCH' not allowed. Allowed are HEAD,GET,POST

Best Answer

You might also find one of the REST API composite resources useful where you want to both update a known record and upsert some potentially new records.

With Composite you could update the Opportunity in the first subrequest and then upsert the child records in further subrequests (up to a maximum of 25 subrequests).

It would be something like the following (roughly done by hand):

{
    "allOrNone" : true,
    "compositeRequest" : [{
        "method" : "PATCH",
        "url" : "/services/data/v39.0/sobjects/Account/0016300000NOteE",
        "referenceId" : "UpdatedAccount",
        "body" : {  
            "Name" : "SampleAccount",
            "Phone" : "1234567890"
        }
    },{
        "method" : "PATCH",
        "referenceId" : "NewContact",
        "url" : "/services/data/v39.0/sobjects/Contact/",
        "body" : {  
            "lastname" : "Smith",
            "title" : "President",
            "email" : "sample@salesforce.com",
            "AccountId" : "@{UpdatedAccount.id}"
        }
    },{
        "method" : "PATCH",
        "referenceId" : "NewContact2",
        "url" : "/services/data/v39.0/sobjects/Contact/",
        "body" : {  
            "lastname" : "Evans",
            "title" : "Vice President",
            "email" : "sample@salesforce.com",
            "AccountId" : "@{UpdatedAccount.id}"
        }
    },{
        "method" : "PATCH",
        "referenceId" : "JunctionRecord",
        "url" : "/services/data/v38.0/sobjects/AccountContactJunction__c",
        "body" : {  
            "Name" : "Test Opty",
            "StageName" : "Prospecting",
            "CloseDate" : "2018-03-19",
            "AccountId" : "@{UpdatedAccount.id}"
        }
    }]
}

Note that the upserts should include the external ID field name and value in the nested urls.

Related Topic