Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Diagram illustrating reduced HTTP calls using the Salesforce Composite API for efficient integration.
Integration

Salesforce Composite API - Reduce Latency and API Limits

Stop wasting your daily limits on dozens of tiny HTTP calls. I'll show you how to use the Salesforce Composite API to bundle requests, handle transactions, and make your integrations way more efficient.

The short answer

The Salesforce Composite API allows developers to bundle multiple REST operations into a single HTTP request to minimize network latency and reduce API limit consumption. It supports transactional rollbacks, record linking through reference identifiers, and dedicated endpoints for handling complex record hierarchies and batch operations.

Key takeaways Bundle multiple REST calls into a single /composite request to reduce round-trip latency and conserve daily API limits. Use referenceId syntax like @{referenceId.id} in the /composite endpoint to link child records to newly created parent records in the same payload. Choose /composite/tree for hierarchical parent-child record trees, /composite/batch for independent tasks up to 25 subrequests, and /composite/sobjects for same-type record collections. Set allOrNone to true to ensure complete transactional rollback across all subrequests if a single operation fails. Account for CPU timeouts, SOQL queries, and DML operations in your subrequests, as standard Salesforce governor limits still apply per transaction.

Ever felt like you're killing your org's performance with a hundred tiny HTTP calls? That's where the Salesforce Composite API comes in. It's one of those tools that, once you start using it, you'll wonder how you ever managed without it. I've seen teams struggle with latency and hitting daily limits just because they were making separate calls for every single record update. But it doesn't have to be that way.

Why you should care about the Salesforce Composite API

Look, the math is simple. Every time your external system talks to Salesforce, there's overhead. You've got the handshake, the headers, and the network travel time. If you're doing that 50 times for 50 records, you're wasting resources. The Salesforce Composite API lets you bundle those operations into one single request. So instead of 50 round-trips, you do one. It's a huge part of building a Salesforce API Integration that actually scales as your data grows.

And it's not just about speed. One of the best things here is transactional control. If you're creating an Account and a Contact, you probably don't want the Account to exist if the Contact fails. With the right settings, this API can handle that "all-or-none" logic for you. If you're already familiar with REST integrations, you know how much of a headache manual rollbacks can be.

Here's a tip: Always use the referenceId. It's the secret sauce that lets you link records together in one go without waiting for the first one to finish and returning the ID to your client.

Breaking down the Salesforce Composite API endpoints

Not all composite requests are the same. Salesforce gives us a few different flavors depending on what we're trying to do. Here's the breakdown of what I actually use in the field:

  • /composite - This is the heavy lifter. You can mix and match different objects and even different methods (like a POST and a PATCH) in one call. You can use the ID from the first step in the second step.
  • /composite/batch - Think of this as a bucket of unrelated tasks. You can send up to 25 subrequests, but they don't talk to each other. If one fails, the others keep going.
  • /composite/tree/sObjectName - Honestly, this is the best way to handle parent-child relationships. You send a nested JSON, and Salesforce builds the whole tree for you in one shot.
  • /composite/sobjects - For those times when you have a bunch of records of the same type, this is your friend. It's a solid way of managing Salesforce large data volumes without moving all the way to the Bulk API.

An architectural diagram illustrating a single API request creating multiple linked parent and child records in a cloud database.

An architectural diagram illustrating a single API request creating multiple linked parent and child records in a cloud database.

Example: Linking an Account and Contact

In my experience, this is the most common use case. You want to create a customer and their primary contact at the same time. Here is how that looks in a standard composite request. Notice how we use the referenceId to link them.


POST /services/data/v60.0/composite
{
  "allOrNone" : true,
  "compositeRequest" : [
    {
      "method" : "POST",
      "url" : "/services/data/v60.0/sobjects/Account",
      "referenceId" : "newAcc",
      "body" : { "Name" : "Cloud Tech Inc" }
    },
    {
      "method" : "POST",
      "url" : "/services/data/v60.0/sobjects/Contact",
      "referenceId" : "newCon",
      "body" : {
        "FirstName" : "Alex",
        "LastName" : "Smith",
        "AccountId" : "@{newAcc.id}"
      }
    }
  ]
}

So what happened there? We told Salesforce to create the Account first. Then, we used @{newAcc.id} to tell the Contact which Account it belongs to. The system handles the ID mapping internally. No extra code is needed on your end. It's clean and efficient.

Example: Using the Tree Resource

Now, if you're doing a deep hierarchy, the Tree resource is even easier. You don't even need the @{...} syntax because the nesting implies the relationship. Here's a quick look at that:


POST /services/data/v60.0/composite/tree/Account
{
  "records" : [
    {
      "attributes" : { "type" : "Account", "referenceId" : "ref1" },
      "Name" : "Global Corp",
      "Contacts" : {
        "records" : [
          { "attributes" : { "type" : "Contact", "referenceId" : "con1" }, "FirstName" : "Sarah", "LastName" : "Connor" }
        ]
      }
    }
  ]
}

Things that might trip you up

Here's the thing: just because it's one HTTP request doesn't mean you've escaped governor limits. One thing that trips people up is thinking this is a "get out of jail free" card for SOQL or DML limits. It isn't. Each subrequest still counts against your transaction limits. If your triggers are heavy, you can still hit CPU timeouts.

Error handling also gets a bit more interesting. When you use allOrNone=true, the whole thing rolls back if one piece fails. That's great for data integrity, but your error parsing logic needs to be ready for it. You'll get a response body that tells you exactly which subrequest failed and why. Don't just check for a 200 OK status; you need to look at the status of each item in the results array.

Key Takeaways

  • The Salesforce Composite API dramatically reduces network latency by bundling calls.
  • Use /composite when you need to link different objects using referenceId.
  • Use /composite/tree for simple parent-child record creation.
  • Remember that governor limits (CPU, DML, SOQL) still apply to every subrequest.
  • Set allOrNone to true if you need the entire batch to succeed or fail together.

Start by identifying your most chatty integrations. If you see a pattern of creating a parent and then immediately creating children, that's your first candidate for a rewrite. It'll save your API limits and make your external systems feel much faster. It takes a little more effort to build the JSON payload, but the performance gains are worth it every single time.

Frequently asked questions

How do you link records in a Salesforce Composite API request?

Assign a referenceId to a parent record creation subrequest, then reference its generated ID in subsequent child subrequests using the @{referenceId.id} syntax. Salesforce resolves the ID mapping internally during request execution.

What is the difference between /composite and /composite/batch?

The /composite endpoint allows subrequests to pass data and link records using referenceId, while /composite/batch runs up to 25 independent subrequests that do not communicate or share data with each other.

Do Salesforce governor limits apply to Composite API requests?

Yes. Each subrequest in a composite payload still counts against platform transaction limits, including CPU timeouts, SOQL queries, and DML limits.

How do you handle rollbacks in Salesforce Composite API?

Set the allOrNone property to true in the request body. If any subrequest fails, Salesforce rolls back the entire set of operations and returns specific error details for each subrequest in the response payload.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment