What batch does
The bundling method. Instead of 50 HTTP round-trips, one request carries a cmd map of method calls. Essential for imports, syncs, and any flow that makes several related calls per event.
Business use cases
- Bulk import/export: 50 records per request instead of 50 requests
- Atomic-ish bundles: create deal + set product rows + add timeline comment
- Read-modify-write pairs: get lead + update lead in one round trip
- Dashboard data collection: several list calls fetched together
Typical fields and parameters
halt— 1 = stop on first error, 0 = continue through failures. Choose per use case and check per-command errors either waycmd— Map of name → 'method?urlencoded=params'. Max 50 entries$result[name]— Chaining token: use a previous command's result in a later command's params — e.g. bind product rows to $result[newDeal]
Example workflow
- Importer reads 5,000 validated rows
- Rows chunked into groups of 50
- Each chunk becomes one batch call of crm.item.add commands
- Worker sends chunks with controlled concurrency and backoff on QUERY_LIMIT_EXCEEDED
- Per-command results reconciled; failed rows logged for a retry pass
Example request
POST .../batch.json
{
"halt": 0,
"cmd": {
"newDeal": "crm.deal.add?fields[TITLE]=Order %238842&fields[CATEGORY_ID]=2&fields[STAGE_ID]=C2:NEW&fields[CONTACT_ID]=512",
"rows": "crm.deal.productrows.set?id=$result[newDeal]&rows[0][PRODUCT_ID]=101&rows[0][PRICE]=4500&rows[0][QUANTITY]=1",
"note": "crm.timeline.comment.add?fields[ENTITY_ID]=$result[newDeal]&fields[ENTITY_TYPE]=deal&fields[COMMENT]=Created by OrderSync"
}
}Example response
{
"result": {
"result": { "newDeal": 3120, "rows": true, "note": 8819 },
"result_error": {},
"result_total": {},
"result_next": {}
},
"time": { ... }
}
// Check result_error per command — a 200 response does NOT mean
// every command inside succeeded.Field mapping notes
- Command params are URL-encoded query strings inside JSON — encode carefully (# → %23, & in values, array bracket syntax)
- $result chaining runs in declaration order; a failed dependency yields empty substitution, not an exception — validate results
- List commands inside batch still paginate; result_next tells you there is more
Security notes
- A batch inherits full scope of its webhook/token — a leaked endpoint that can batch is 50× the damage per request; same secret discipline as everywhere
Common errors
- Silent partial failure — Only checking HTTP 200 — iterate result_error and reconcile counts
- Chained command got empty ID — Dependency failed or name typo in $result[] — validate the dependency's result before trusting downstream effects
- Encoding bugs (fields truncated at & or #) — URL-encode every param value; build cmd strings with a proper encoder, never string concatenation
- Still hitting rate limits — Batches count too — add inter-batch delay and concurrency caps; you've reduced requests 50×, not infinitely
Production implementation tips
- Wrap batch in a client helper that builds commands with proper encoding, checks result_error, and retries failed commands individually
- Keep bundles logically related — a 50-command grab-bag is undebuggable
- For imports: idempotent commands (search-before-create keyed on external ID) make failed-chunk retries safe
Webhook or OAuth app?
Works identically with both; the auth decision is unchanged.
Full decision guide: webhook vs OAuth app in Bitrix24.
When to use a queue worker
batch and queue workers are complements, not alternatives: the queue controls concurrency and retries; batch multiplies per-request throughput.
How Tech Titan can help
Tech Titan builds production Bitrix24 integrations around batch and its siblings — with authentication, field mapping, queue workers, retry logic, duplicate handling, and structured logs as standard. If this method is on your critical path, bring the requirement to a free audit call and leave with an architecture sketch.