Skip to content

Many in One Call

Module 3 of 7 in the chapter Salesforce as an API Provider, chapter 8 of the Integration Architect course. Each module stands on its own. Previous: REST First · Next: GraphQL and the UI API

The question this module answers: When a caller needs to send many records in one go, especially records that belong together, which of Salesforce’s composite resources does it use?

On the map: Many in one call On the map: Many in one call. One row from the map of every door into Salesforce, in module 1: the set many in one call, with its doors: sObject Collections, sObject Tree, Composite and Composite graph. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.57.1", "built": "2026-10-31", "id": "DGM-INT-SP-10", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.5.0", "theme": "stevetecharc 1.4.0"} THE SET: WHAT THE CALLER IS DOING THE DOORS Many in one call one call against the allowance sObject Collections 200 to write, 2,000 to read · ch 8.3 sObject Tree parents with children · ch 8.3 Composite 25 steps, values passed along · ch 8.3 Composite graph 500 per graph, all or nothing · ch 8.3 One set from the map of every door into Salesforce (module 1). HOW TO READ IT taught in this chapter © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Where this module sits on the map.

Module 2 worked one record per call. That’s fine for a few updates an hour. Now look at what Redrock actually sends Steve Trucking every evening: a manifest. One manifest, the deliveries on it, and the items in each delivery. Take a small one: one manifest, three deliveries, two items each. That’s ten records.

One record per call means ten calls. And it’s worse than ten, because the records depend on each other. Each Work Order needs the manifest’s Salesforce ID, and each line item needs its Work Order’s ID. So the caller inserts the manifest, waits, reads the new ID, inserts the deliveries, waits again, and so on.

Two things go wrong.

The API allocation runs out. Every call counts against the org’s daily allocation (module 7). I’ve had clients hitting their API limits because too many inserts and updates were coming in one at a time. Now picture a partner updating a delivery and its items and its status, over and over, at a high rate. Done one at a time, you’re going to saturate your APIs.

Half a manifest gets saved. Call six fails. The manifest and two deliveries are in Salesforce, and the rest aren’t. Now somebody has to work out what got in, and the dispatchers are planning tomorrow’s routes from half a manifest.

Salesforce’s answer is a family of resources that send many records in one call. The family has four members, and they’re easy to mix up, so here they are one at a time.

sObject Collections: Many of the Same Kind

Section titled “sObject Collections: Many of the Same Kind”

The simplest. A list of records, in one call:

  • Create, update or delete up to 200 records in one request. A list for create or update can even mix object types.
  • Upsert up to 200 records of one type by an external ID, from API 46.0.
  • Get up to 2,000 records of one type by their IDs.

“The entire request counts as a single call toward your API limits” (sObject Collections (opens in a new tab), REST API Developer Guide, Winter ‘27, checked 2026-10-31). If Redrock only needs to update the status on 150 deliveries, this is the tool: one upsert of 150 Work Orders by Partner_Delivery_Key__c, one call.

Three details from my own demos are worth knowing before you build on it:

  • The answers come back in the order you sent. Record three’s result is the third in the list, with its new ID or its errors. The caller matches them up by position.
  • Mixed types run in chunks. Send two accounts, a contact, then another account, and Salesforce processes three chunks: the two accounts, the contact, the last account. One request can have up to 10 chunks, so sort the list by type before you send it. And you can’t mix records tied to Setup, like users, with ordinary records in one call: Salesforce’s mixed DML rule (Create Records Using sObject Collections (opens in a new tab), checked 2026-10-31).
  • All or none is a flag you set. Off, which is the default, each record succeeds or fails on its own. On, one bad record rolls back the rest, and each of them comes back marked ALL_OR_NONE_OPERATION_ROLLED_BACK, so the caller can tell the record that failed from the ones that were only rolled back.

What Collections can’t do is link a new child to a new parent. The parent’s ID doesn’t exist yet when the request is sent.

The tree is built for exactly that. You send the parent with its children nested inside it, and Salesforce creates them and links them for you:

  • up to 200 records across all the trees in one request;
  • up to five levels deep;
  • up to five different object types.

One request, one API call (sObject Tree (opens in a new tab), checked 2026-10-31). A manifest with its Work Orders, and each Work Order with its line items, is three levels. It fits.

Your rules run on the tree too. When I recorded the video on it, my sandbox’s duplicate rules stopped the request: two of the contacts I was sending matched contacts already there. Salesforce did exactly what it should. If any record in a tree fails, “the entire request fails” (sObject Tree (opens in a new tab)), so nothing was half-saved. I changed the data and sent it again.

The tree only creates. It can’t update a delivery that’s already there, and it can’t upsert. A manifest that’s sent again with one change needs something else.

Composite is the general one. You send a list of ordinary REST requests, up to 25 subrequests, and up to 5 of them can be queries or Collections. Each subrequest gets a name, a reference ID, and a later subrequest can use the earlier one’s result:

{
"allOrNone": true,
"compositeRequest": [
{ "method": "PATCH",
"url": "/services/data/v68.0/sobjects/Manifest__c/Partner_Manifest_Key__c/REDROCK-20261031",
"referenceId": "manifest",
"body": { "Delivery_Date__c": "2026-11-01" } },
{ "method": "PATCH",
"url": "/services/data/v68.0/sobjects/WorkOrder/Partner_Delivery_Key__c/REDROCK-8472914-1",
"referenceId": "delivery1",
"body": { "Manifest__c": "@{manifest.id}" } }
]
}

That’s what I like about composite. Insert this record, put its new ID in a variable, use the variable in the next step. A series of actions, and “the entire series of requests counts as a single call toward your API limits” (Send Multiple Requests Using Composite (opens in a new tab), checked 2026-10-31). And because every step is a normal request, it can upsert by Redrock’s own keys, as in module 2.

Look at allOrNone at the top. It’s off unless you turn it on. Off, a failed step stops only the steps that depend on it, and Salesforce warns this “can lead to a mix of processed and unprocessed records”. On, one failure rolls back the whole request (Using Composite Graphs (opens in a new tab), checked 2026-10-31). For a manifest, you want it on.

Twenty-five steps is the catch. Our small manifest is ten records. A real one, with dozens of deliveries, isn’t.

The composite graph is composite grown up. Each graph is a set of connected subrequests, and Salesforce guarantees that the steps in a graph are “either all completed or all not completed” (same page). The limits are much bigger:

  • up to 500 subrequests in one graph;
  • up to 75 graphs in one request;
  • up to 15 levels deep

(Composite Graph Limits (opens in a new tab), checked 2026-10-31).

That changes how Redrock can send its manifests. One graph per manifest: if any delivery on it fails, that whole manifest rolls back and comes back as a failure, and the other manifests in the same request still go in. Nobody has to work out which half of which manifest got saved.

One manifest, one call One manifest, one call. On the left, Redrock's system sends tonight's manifest. In the middle, one composite graph request: one API call, all or nothing for this manifest. On the right, in Steve Trucking's org, the records it creates or updates, by Redrock's own keys: the manifest; three Work Orders, each linked to the manifest; and six Work Order Line Items, two linked to each Work Order. Underneath: done one record at a time, the same manifest is ten calls, and a failure part way leaves half a manifest saved. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.57.1", "built": "2026-10-31", "id": "DGM-INT-SP-02", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.5.0", "theme": "stevetecharc 1.4.0"} REDROCK'S SIDE ONE REQUEST INSIDE STEVE TRUCKING'S ORG Redrock's system tonight's manifest, with Redrock's own keys One composite graph one API call; all or nothing for this manifest one call The manifest 1 record, upserted by its key Three Work Orders each linked to the manifest Six Work Order Line Items two linked to each Work Order sends upserts, step 1 upserts, step 2 upserts, step 3 One record at a time, the same manifest is ten calls, and a failure part way leaves half a manifest saved. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

One manifest, one call, and it goes in whole or not at all.

You need to sendUseLimit (Winter ‘27)All or nothing
Many records of one kind, no new parentssObject Collections200 to write, 2,000 to readOptional, for the whole request
New parents with their new childrensObject Tree200 records, 5 levelsYes
A few steps that pass values along, including upsertsComposite25 subrequestsOptional, for the whole request
Related records at scale, each set whole or not at allComposite graph500 per graph, 75 graphsYes, per graph

There’s a fifth name you’ll see, Composite Batch, and it’s different in the way that matters. It runs up to 25 independent requests, but “each subrequest counts against rate limits”, nothing passes between them, and nothing rolls back (Composite Batch (opens in a new tab), checked 2026-10-31). It saves round trips, not API calls.

I sum it up as your tools for insert, by complexity. A single record: the plain sObject call from module 2. A list: Collections. Parents and their children: the tree. Steps that depend on each other: composite. And a set that must go in whole: the graph.

Two things stay true for all of them. Your automations still run, on every record, as module 2 said, so a ten-record call runs ten records’ worth of triggers and flows. And none of them is the bulk door. Hundreds of records that belong together, use composite. Thousands, or millions, go through chapter 10. Salesforce draws the line at about 2,000: more than that “is a good candidate for Bulk API 2.0”, and fewer is better done with “‘bulkified’ synchronous calls in REST (for example, Composite)” (Which API Do I Use? (opens in a new tab), Salesforce Help, checked 2026-10-31).

Test knowledge. Know when composite beats bulk. Thousands of records of one object, like accounts only: the Bulk API. Parents and children together, accounts with their contacts and opportunities, arriving many times a minute: composite, because one call carries the whole set and counts once against the allowance. And know Salesforce’s line: more than 2,000 records, consider Bulk API 2.0; fewer, bulkified REST calls such as composite.

In 2023 I made two videos on inserting many records at once: the composite tree, then collections and composite. The notes under the videos say what’s still right and what’s changed since.

STA 1.13 · Inserting Lists of Objects, Across the APIs, Salesforce REST API Composite Tree · 9:47 · published 2023-11-13 · plays from YouTube when you click it · Watch on YouTube · More videos: Salesforce Integration Architecture Videos
STA 1.14 · Inserting Lists of Objects Part 2, Across the APIs, Salesforce REST API Composite · 13:13 · published 2023-11-10 · plays from YouTube when you click it · Watch on YouTube · More videos: Salesforce Integration Architecture Videos
  • Where the all-or-nothing line is. Per record, per request, or per graph. For records that only make sense together, like a manifest and its deliveries, draw the line around them.
  • Which resource, by the shape of the work. Same kind: Collections. New parent with children: Tree. Steps with upserts: Composite. Sets that must go in whole, at scale: Composite graph.
  • The caller’s keys, all the way down. Upsert by external IDs at every level, so a resend updates instead of duplicating.
  • What a failure sends back. Each resource answers with a result per record or per step. The caller reads them, and the design says who fixes what.