v1.2.0

Choosing the right method

Decision guide for picking between Call, CallList, FetchList, Batch and BatchByChunk in REST API v2 and v3.

Overview

The SDK exposes five primitives for talking to the Bitrix24 REST API, all reached through b24.actions.v{2,3}.<primitive>.make(options). They look similar but have very different cost profiles. Picking the wrong one is the single most common source of slow apps and "why is my dashboard hammering the queue?" tickets — so this page exists to make the decision in 30 seconds.

Three axes drive the choice:

  1. One call or many? A single REST method or several at once.
  2. Bounded or unbounded? Do you know up front there are ≤ 50 results, or could there be 50 000?
  3. All-at-once or stream? Need every record in memory for aggregation, or process them as they arrive?
The instance-level shortcuts on AbstractB24 (b24.callMethod(), b24.callBatch(), b24.callListMethod(), b24.fetchListMethod(), b24.callBatchByChunk()) are @deprecated and slated for removal in v2.0.0. They emit a runtime warning on every call and ignore the API-version split. Always call the action explicitly: b24.actions.v2.call.make({…}) / b24.actions.v3.batch.make({…}) etc. See the v0 → v1 migration guide for one-to-one rewrites.

Decision matrix

Your situationUse
One method, one record (crm.deal.get, tasks.task.get)Call
One list method, ≤ a few thousand records, you need the full array in memoryCallList
One list method, tens of thousands of records, processed in chunks (CSV export, ETL)FetchList
Multiple different methods you want to fire in one round-trip (dashboard tile load)Batch
Many calls of the same shape (bulk create / update / delete > 50 items)BatchByChunk

Then pick the API version: prefer v3 for any method available in v3 (better filtering, larger pages, server-side optimization), and v2 for everything else. The SDK's v2 Call.make() even logs a warning when you call a v3-eligible method on v2 — that's your prompt to migrate.

Per-method tradeoffs

Call.make()

Use when you need exactly one record or one server-side operation (update, add, delete).

Avoid when you find yourself wrapping it in a for loop with await — that's the signal to switch to Batch or BatchByChunk. A loop of N Call.make() calls is N round-trips; Batch collapses up to 50 into one. BatchByChunk collapses any number into ceil(N / 50) round-trips.

CallList.make()

Use when the result set is small enough to hold in memory and you'll do something cross-cutting on it (sort, group, aggregate, dedupe, pass to a chart library).

Avoid when you only need a small slice — pass select and filter to narrow the result instead of fetching everything. The method always fetches every page that matches your filter; "give me top 10" with no filter is wasteful.

FetchList.make()

Use when the result is unbounded (or could be), and you can process records as soon as they arrive: stream them to a CSV, push them into a queue, write them to a database, send them over a WebSocket.

Avoid when you need cross-record aggregation that requires the whole set in memory — CallList is simpler. The generator yields chunks of 50 (v2) or options.limit up to 1000 (v3); your downstream code must handle each chunk before the next request fires, so heavy synchronous work between chunks slows the overall scan.

Batch.make()

Use when a single user action depends on data from several different methods. A typical example is a dashboard tile that needs the user's profile, their open deals count, and their pinned tasks — three different methods, one round-trip.

Avoid when the same method is repeated 50+ times. That's exactly what BatchByChunk is for, and Batch will reject anything over 50 commands. Also avoid when you need named output keys and > 50 calls — BatchByChunk deliberately only accepts array-of-tuples / array-of-objects (named commands break across chunk boundaries).

BatchByChunk.make()

Use when you have an arbitrary number of commands of the same shape — bulk migrations, mass create / update / delete, exporting per-id details for thousands of related records.

Avoid when you only have a handful of calls — Batch is simpler and gives you named results. Also avoid when you need transactional behavior — BatchByChunk is not atomic. If chunk 7 of 30 fails, chunks 1-6 are already applied; chunks 8-30 may or may not run depending on isHaltOnError.

Limits at a glance

MethodMax callsMax pageReturnsThrows on first error?
Call.make()1n/aAjaxResult<T>No (check isSuccess)
CallList.make()unbounded (paged)50 (v2) / 1000 (v3)Result<T[]>No
FetchList.make()unbounded (streamed)50 (v2) / 1000 (v3)AsyncGenerator<T[]>Yes — SdkError
Batch.make()50n/aCallBatchResult<T>Configurable via isHaltOnError
BatchByChunk.make()unbounded (chunked × 50)n/aResult<T[]>Configurable via isHaltOnError

Common anti-patterns

  • b24.callMethod() / b24.callBatch() / b24.callListMethod() / b24.fetchListMethod() / b24.callBatchByChunk(). Deprecated shortcuts on AbstractB24. They still work but emit a warning on every call and will be removed in v2.0.0. Migrate to the matching b24.actions.v{2,3}.<primitive>.make({…}) — see the v0 → v1 migration guide for the one-to-one mapping.
  • for (const id of ids) await b24.actions.v2.call.make(...). N IDs = N round-trips. Use actions.v2.batch.make if ids.length ≤ 50, actions.v2.batchByChunk.make otherwise.
  • actions.v2.callList.make → actions.v2.callList.make → actions.v2.callList.make for related entities. This is the cause of most slow dashboards. Fetch the parent list once (actions.v2.callList.make or actions.v2.fetchList.make), then load related records via one actions.v2.batch.make per chunk of 50 IDs.
  • Custom order on actions.v{2,3}.callList.make / actions.v{2,3}.fetchList.make. Cursor pagination needs order: { idKey: 'ASC' }. Any user-supplied order is stripped with a runtime warning (see Limitations). Use filter to narrow the slice instead.
  • actions.v{2,3}.batch.make with named commands across > 50 items. Either split manually into multiple batch.make calls, or switch to actions.v{2,3}.batchByChunk.make and accept ordered results.
  • Mixing v2 and v3 methods in one actions.v3.batch.make call. BatchV3 pre-validates the call list and throws SdkError with code JSSDK_CORE_METHOD_NOT_SUPPORT_IN_API_V3 if any method isn't v3-supported. Split the batch by API version, or use actions.v2.batch.make.

See also