Salesforce recently added the composite resources (batch, tree, and composite) to the Salesforce REST API. You can use the composite resources to make multiple requests using a single REST API call. Using the composite resources means you can simplify your code, reduce network overhead, and improve your app’s performance — the days of making many separate REST API calls when doing large-scale data operations are over!

A Simple Example

Suppose you wanted to programmatically create a new Account and then assign an existing Contact to the Account you just created. A typical approach would do something like the following:

  • Use the SObject Basic Information resource to create a new Account record via a POST to /services/data/v38.0/sobjects/Account.
  • Use the Query resource to obtain the ID of an existing Contact via a GET to /services/data/v38.0/query.
  • Use the SObject Rows resource with the Account ID and Contact ID to update the existing Contact and assign it to the Account via a PATCH to /services/data/v38.0/sobjects/Contact.

In most cases this would require at least three REST API calls. That’s a fair amount of round-trips to Salesforce and back for a relatively simple task.

Using the composite resources, you can do the entire task in a single REST API call, with a request body that contains all the logic. We’ll show the complete composite resources request for this example later on, but first let’s take a look at these new resources!

The Composite Resources

Salesforce provides three composite resources. These are (in increasing order of complexity and flexibility):

composite/batch/: Execute a set of subrequests in a single request. Subrequests are executed independently and information can’t be passed between subrequest calls.

composite/tree/: Create one or more sObject trees (a collection of nested, parent-child records with a single root record) in a single request. All tree root records must be the same type.

composite/: Execute a series of REST API subrequests in a single call. The output of one subrequest can be used as input to a subsequent subrequest.

We’ll go into more detail on each resource, but if you’re trying to decide which resource to use, consider using dependencies between calls as a deciding factor. If you’ve got a bunch of unrelated calls and want to reduce the number of roundtrips from your client, use batch. If you’re creating a bunch of records that live in the same parent-child hierarchy, use tree. If you’ve got a bunch of calls that might need to use results from one call as input to another, use composite. Simple, right?

The composite resources shouldn’t be used in place of existing APIs that are designed to handle asynchronous uploads or modifications of large batches of records, like the Bulk API.

Using batch

Use the batch resource when you’ve got a bunch of independent REST API calls that don’t depend on each other in any way. To make a batch resource call, issue a POST to instance endpoint/services/data/API version/composite/batch/ with a request body that contains an array of REST API subrequests. For each subrequest in the array, you specify the HTTP method (GET, POST, PATCH, etc), the resource URL, and other optional request attributes as needed.

Here’s a request body example that contains a describe call on Account, followed by an update to change a particular Contact’s Title field, followed by a request to get the current API limits:

You’ll get back a response that contains an array of subrequest results.

A couple important things to note:

  • You can make up to 25 subrequests in a single batch call.
  • While the calls can’t depend on each other, they are called in the order specified in the request data.
  • In API version 34.0 and later, subrequests can be calls to the Limits, SObject, Query/QueryAll, Search, Connect, and Chatter resources. API version 35.0 adds the ability to use Actions resources.
  • You can’t use different API headers for different subrequests. You can only use API headers that apply to the overall batch call.
  • You can specify what Salesforce should do if a subrequest fails using the haltOnError request field. More on this in a future blog post soon!
  • If a particular subrequest takes longer than 10 minutes to execute, the entire batch call times out and subsequent subrequests are not executed.
  • If a subrequest in a batch fails, previous successful subrequests are not rolled back. Make sure to check the batch response in this scenario to understand what succeeded and what failed!

Using tree

Use the tree resource to create multiple object records of the same type, along with child records, in a single call. To make a tree resource call, issue a POST to instance endpoint/services/data/API version/composite/tree/SObject Name/ with a request body that contains one or more SObject record trees.

What’s an SObject record tree? It’s a single record, with zero or more child records, which in turn can have nested child records as well. So, for example, a single Account SObject tree could have information for the “MyCompany” account and two related Contacts: “John Smith” and “Sarah Brown”.

Here’s an example request body that uses two single-record SObject trees to create two unrelated Account records, with each Account record having no child records:

And here’s an example request body that uses one SObject tree to create a single Account record along with two child Contact records:

The response will contain an array of created record IDs along with the associated reference IDs you supplied in the request.

Some things to keep in mind:

  • The root record of each SObject tree must be same type you specify in the resource call. So, for example if you make a tree resource call using /services/data/API version/composite/tree/Account/, all SObject trees you specify in the request body must start with an Account record.
  • You can create a maximum of 200 total records in a single tree resource call. This can be split across any number of SObject trees.
  • SObject trees can be a maximum of 5 levels deep, so at most a single “root” record and 4 levels of nested child records. However, this can be further limited by the number of object types in the request as described in the next bullet.
  • Across all your SObject trees in a given request, you can use a maximum of 5 different types of objects. So, if your first tree had an Account, a child Contact, and a grand-child Opportunity, your next tree could introduce at most 2 additional object types (for example, maybe a tree with an Account, a child Order, and a grand-child Quote).
  • When records are created, triggers, processes, and workflow rules fire separately for different groups of records. See the documentation on tree resource for more details.

Using composite

Use the composite resource when you need to take input from one subrequest and use it in another subrequest. Unlike the batch resource, the composite resource lets you create dependencies between subrequests. To make a composite resource call, issue a POST to instance endpoint/services/data/API version/composite/ with a request body that contains an array of subrequests. For each subrequest in the array, you specify the HTTP method (GET, POST, PATCH, etc), the resource URL, and other optional request attributes as needed. You’ll also provide a reference ID for each subrequest, and you’ll use this reference ID to pass output from one subrequest to the input of another.

Here’s an example request body that creates an Account record, and then creates a Contact record, using the ID of the created Account:

Notice how the Account ID (that Salesforce creates) is used when creating the Contact by referring to the Account’s reference ID.

You’ll get a response that contains an array of subrequest results.

The composite resource provides greater flexibility than batch or tree. You can almost think of batch and tree as “flavors” of composite. In fact, you could duplicate the same basic behavior of batch or tree using composite!

Some things to keep in mind:

  • Subrequests can be calls to SObject and Query/QueryAll resources.
  • Unlike the batch resource, you can specify different REST API headers for each subrequest using the httpHeaders field. Note that not every REST API header is allowed for a subrequest — for more details on which headers can be used for subrequests, see Composite Subrequest in the REST API Developer Guide.
  • You can have up to 25 subrequests in a single call. Up to 10 of these subrequests can be query operations.
  • You can specify what Salesforce should do if a subrequest fails using the allOrNone request field. More on this in a future blog post coming soon!

A Simple Example, Now Using Composite!

Let’s look at how we’d execute the simple example we originally introduced using the composite resources. As we mentioned, the goal is to create a new Account, find an existing Contact, and associate the existing Contact with the Account. Since we’ll need to use the results from creating the new Account when updating the Contact, we’ll use the composite resource.

Using composite, you’d simply do a single POST request to your instance with a URI of /services/data/v38.0/composite/ and a request body that looks something like this:

Notice how we’re able to reference information from the new Account in our Contact field (via @{refAccount.id}), and use query results information in the PATCH call URL (via @{refContact.records[0].Id}), all within a single REST API request.

More Information

Hopefully you’ve now got a feel for what the composite resources do, and maybe some ideas on where you can use them in your code.

We’ll go into more details on how the composite resources handle errors, and how you can control subrequest execution when errors occur, in a future blog post.

Feel free to check out the official docs, which include a series of more complex examples. For more information on the composite resources, see:

Examples and walkthroughs of using the composite resources in the REST API Developer Guide.
Reference documentation on the composite resources in the REST API Developer Guide.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS