[SalesForce] how to add multiple records to relate list via rest api

What exist

So I've custom Object called Credit Memo where I want to relate one Order and I want multiple OrderItem in the Relate List(Related Tab). I don't have Master-Detail relationship. Or by using lookup relationship I can only relate one record?

As it's easy to relate order as I only have to relate one so I can just search and select but
I'm unable to figure out how to add Order Item using basic UI also because I don't have any option in a Related tab for adding the Order Item but the Related list still shows me Order Products Tab.

I want to achieve these using REST API too, I've tried composite tree but it fails(as I'm not doing it properly of course).

What I want

Is there any way of adding multiple child records to the custom object using REST API? Like Array of Id's to realte?

Sorry, Maybe I'm missing basics of how Salesforce work as I'm beginner.

UPDATE: I think my question is little confusing, so here's the simpler question I thought of – "How to link existing OrderItem to the custom object using REST API while creating the Record of that Custom object."

UPDATE

I was doing something horribly wrong, now I can relate OrderItems exactly the way I want by doing following.

  1. Create Credit Memo

  2. Go to OrderItem search and select Credit Memo Save

  3. Do above for another OrderItem

By doing this I've two OrderItems in Credit Memo.
So If I'm not wrong I've to do same via REST.

  1. Insert Credit Memo via REST and save the response Id.

  2. Update the existing OrderItem and set saved Credit Memo id to Credit Memo Lookup field.

  3. Do above for another OrderItem.

But is there any way doing this opposite? Like while creating the Credit Memo how can I give both ID's and relate them? So it will minimize my update API calls

API Service I'm trying

Endpoint
https:///services/data/v42.0/composite/tree/Credit_Memo__c/

Request Body
(I know this is the dumbest way a one can think of)

{
  "records":[
    {"attributes":{"type":"Credit_Memo__c","referenceId":"ref1"},
     "Name":"Test",
     "Order_Product__c":{
       "records":[
         {"attributes":{"type":"OrderItem","referenceId":"ref2"},
         "Id":"80229000000zltwAAA"}
       ]
     }
    }
  ]
}

Error

[
    {
        "message": "Cannot deserialize instance of reference from START_OBJECT value { or request may be missing a required field at [line:4, column:19]",
        "errorCode": "JSON_PARSER_ERROR"
    }
]

Best Answer

I was waiting for some downtime to dive head-first into this, but that didn't really materialize.

I've just finished answering a similar question though, so this topic is fresh in my mind.

Like I said in my comment, I believe the "tree" resource to be the correct one to use. The documentation on the SObject Tree resource isn't exactly the clearest, but it does mention that you can nest up to 5 levels of child records in a single request.

One thing to note is that when you are using the SObject Tree resource to create records (or just try to create records in general), you do not specify an id for any of the records. The referenceId here is used by Salesforce to automatically set the appropriate relationship field (this will be important in a bit).

It's not entirely clear from your question what your object hierarchy is, but let's take a look at the example request from the create nested records documentation

{
"records" :[{
    "attributes" : {"type" : "Account", "referenceId" : "ref1"},
    "name" : "SampleAccount1",
    "phone" : "1234567890",
    "website" : "www.salesforce.com",
    "numberOfEmployees" : "100",
    "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"
         }]
      }
    }
    // rest of request truncated
  ]
}

This is for creating an Account and immediately creating a Contact related to the Account.

The big difference between what you have and what this example shows is the label that contains the child records. It's a subtle difference unless you're familiar with parent-child subqueries in SOQL. Your attempt tries to use the name of the child SObject, whereas the documentation uses the child relationship name (Contacts instead of Contact).

The short explanation for why we use the child relationship name is because creating a master-detail or lookup relationship on a child object also causes a special "field" to be created on the parent object. This special "field" holds a List<SObject> (specifically a List of the child sobject's type), and its API name is the same as the child relationship name that you set when you create the relationship field on the child object.

It's hard to know what your child relationship name is between Credit_Memo__c and Order_Product__c, but it's likely Order_Products__r (the plural, and changing __c to __r). You can check this for yourself by looking at the detail page for your lookup relationship on the Order_Product__c object.

So, that all said, a well-formed request to accomplish what you're looking to do should look like this (make sure to remove my comments, as JSON doesn't support them)

{
  "records":[
    {"attributes":{"type":"Credit_Memo__c","referenceId":"ref1"},
     "Name":"Test",
     // You need to use the relationship name, and __r since it's a custom relationship
     "Order_Products__r":{
       "records":[
         // type name in the attributes here should match the API name of your object
         {"attributes":{"type":"Order_Product__c","referenceId":"ref2"},
          // Do not specify Ids, but be sure to include any other required fields
         },
         {"attributes":{"type":"Order_Product__c","referenceId":"ref3"},
           // If you want to populate data from your credit memo record, you may
           //   be able to use @{ref1.<field api name here>}, assuming that it's
           //   either the Id of your parent object, or one of the fields that
           //   you set (like "Name" in this example => @{ref1.Name})
           // I have, however, not tested this myself
         }
       ]
     }
    }
  ]
}
Related Topic