Drawing 1 · Interactive
Send one batch, get three answers back
https://graph.facebook.com/v26.0/POST 200 in 900 ms(simulated)
Request
2 headers · bodyResponse
200 OKResponse: 200 OK after 900 ms.
What is a Graph API batch request?
A Graph API batch request bundles several independent Graph API calls into a single HTTP request. You POST to the Graph root — https://graph.facebook.com/v26.0/ — with a batch parameter holding a JSON array of up to 50 operations, each with a method and a relative_url and, for POST and PUT, an optional URL-encoded body. Meta runs the operations and returns one HTTP response whose body is an array of logical responses in the same order, each with its own code, optional headers and a body that is itself a JSON-encoded string.
Batches cut connection overhead and latency when a job needs many small calls: reading the quality rating of 40 phone numbers, fetching the status of dozens of templates, or updating settings across several WABAs. Operations can be named and referenced, so a later operation can take IDs from an earlier result with JSONPath, for example ?ids={result=numbers:$.data.*.id}. A top-level access token is always required, and individual operations may carry their own tokens, which lets a partner batch calls across several customers' business tokens.
Batching is not a way around limits. Each operation counts separately toward app and business use case rate limits, so 50 calls in one batch cost the same quota as 50 single calls. Nor is it a broadcast tool: the Cloud API's /messages endpoint sends one message to one recipient per call, and large sends are governed by throughput and messaging limits whatever the transport. Use batches to cut round trips on management work and a paced queue for messages.
Key takeaways
- A Graph API batch request sends up to 50 calls in one HTTP POST and gets back an array with one result per call.
- Each call in a batch counts separately toward rate limits: batching saves round trips, not quota.
- Each item's
bodycomes back as a JSON-encoded string, and items that did not complete come back asnulland can be retried. - Named items can feed later ones through JSONPath references such as
{result=numbers:$.data.*.id}. - Use batches for WhatsApp management reads and writes; /messages sends one message per call, so a batch is never a broadcast.
Implementation
A Graph API batch request in code
curl -X POST "https://graph.facebook.com/v26.0/" \-F "access_token={ACCESS_TOKEN}" \-F "include_headers=false" \-F 'batch=[{"method":"GET","name":"numbers","relative_url":"{WABA_ID}/phone_numbers?fields=id&limit=10"},{"method":"GET","relative_url":"?ids={result=numbers:$.data.*.id}&fields=display_phone_number,quality_rating"},{"method":"GET","relative_url":"{WABA_ID}/message_templates?fields=name,status&limit=50"}]'
The second operation reads the IDs returned by the first one, named numbers, through a JSONPath reference.
Operating sequence
How does a Graph API batch request work?
Build the operations
Create a JSON array of up to 50 objects with
methodandrelative_url(relative to the version in the URL), adding anameto any operation a later one depends on.POST it to the Graph root
Send
batch=[…]with a top-level access token tohttps://graph.facebook.com/v26.0/. Addinclude_headers=falseto drop per-item headers you do not need.Read the array in order
The response is an array aligned with your operations. Each item has a
codeand abodystring; parse the body before reading any field.Handle partial results
Some items can fail with their own error while the rest succeed, and items that did not complete are
null. Retry only the failed or null operations.Respect rate limits
Every operation counts toward quota. Watch usage, keep batches modest under load and back off on throttling errors such as 4 or 80008.
Design intent
Why does a Graph API batch request matter?
Management jobs that fan out across many numbers or templates are dominated by network round trips. Folding 50 calls into one request can turn a sync that took minutes into seconds and reduces connection churn on your side. Understanding the per-item behaviour — partial failures, null results, string-encoded bodies, quota still counted per call — is what separates a faster integration from a batch job that silently drops half its work.
Specifications
A Graph API batch request: key facts and limits
- Maximum operations
- 50 per batch
- Endpoint
- POST https://graph.facebook.com/v26.0/
- Per-operation fields
- method, relative_url, body, name
- Response
- Array of {code, headers, body}; body is a JSON string
- Incomplete operations
- Returned as null; retry them
- Rate limits
- Every operation counts separately
- Tokens
- Top-level token required; per-item tokens allowed
- Drop headers
- include_headers=false
Failure modes
Common mistakes with a Graph API batch request
Expecting batching to save quota
Each operation counts toward app and business use case limits. A batch of 50 costs 50 calls; it only saves round trips.
Treating the outer 200 as success
The batch itself succeeds even when items fail. Check every item's
codeand parse itsbodyfor anerrorobject.Forgetting the body is a string
Item bodies are JSON-encoded strings, so
item.body.idis undefined. Parse each body first.Dropping null items
Operations that did not complete come back as
null. Without a retry for them, a sync silently skips records.Using batches as a broadcast engine
Messages still go one recipient per /messages call, under throughput and messaging limits. Send campaigns from a paced queue, not from giant batches.
Recommended practice
Best practices for a Graph API batch request
- Keep batches below 50 when operations are heavy; slow items are the ones that come back null.
- Name operations and use JSONPath references instead of a second round trip for dependent reads.
- Log the index and relative_url of every failed item so retries are targeted.
- Run large batch jobs off-peak so they do not starve interactive calls of shared quota.
Example: A nightly health sweep for 120 numbers in Pune
A Pune logistics aggregator manages 120 WhatsApp numbers for regional warehouses. Its nightly job used to make 120 sequential GET calls for each number's quality_rating and verified_name; now it sends three batches of 40. One night the third batch returns two null items and one item with code 400, because a number had been deleted. The job re-queues the two nulls, flags the deleted number to ops and finishes in seconds. Because every item still counts toward the business use case limit, the job runs off-peak, away from the daytime template sync that shares the same quota.