POST https://api.pushwoosh.com/messaging/v2/notify/batch
Sends several messages in one call. Every item is an independent Notify : it is validated exactly like a standalone Notify request, and it gets its own result.
Read the results, not the status code
The call itself returns HTTP 200 as long as the batch envelope is valid — even if every single item failed. A failing item never fails the whole request. Always check results[] and the succeeded / failed counters; do not treat a 200 response as confirmation that messages were sent.
This is not a faster way to send
NotifyBatch does not send messages faster than calling Notify directly. If your integration can already issue requests concurrently, running Notify in parallel threads/workers gives the same throughput — HTTP/2 handles that by design. Use NotifyBatch for convenience when your integration is not built for concurrency, not for speed.
"item_id" : " caller-defined-id " ,
Field Type Description itemsarray of NotifyBatchItem Required, 1 to 500 entries (server-configured limit). Items are processed concurrently; results come back in request order regardless.
Field Type Description item_idstring Optional caller-supplied correlation id, echoed back on the matching result. Not used by Pushwoosh otherwise. requestNotifyRequestSame body as a single Notify call — segment or transactional, transaction_id included. Required.
schedule is still required per item
Each item’s request needs its own schedule, exactly like a standalone Notify call. Omitting it does not fall back to “send now” — the item fails with an EmptySchedule error.
curl -X POST https://api.pushwoosh.com/messaging/v2/notify/batch \
-H " Authorization: Token YOUR_API_TOKEN " \
-H " Content-Type: application/json " \
"application": "XXXXX-XXXXX",
"platforms": ["IOS", "ANDROID"],
"users": { "list": ["user-123"] },
"en": { "ios": { "body": "Your order has shipped." } }
"schedule": { "at": "2026-05-01T12:00:00Z" },
"message_type": "MESSAGE_TYPE_TRANSACTIONAL",
"transaction_id": "order-1001-shipped"
"application": "XXXXX-XXXXX",
"platforms": ["IOS", "ANDROID"],
"users": { "list": ["user-456"] },
"en": { "ios": { "body": "Your order has shipped." } }
"schedule": { "at": "2026-05-01T12:00:00Z" },
"message_type": "MESSAGE_TYPE_TRANSACTIONAL",
"transaction_id": "order-1002-shipped"
"message_code" : " XXXXX-XXXXX-XXXXX " ,
"unknown_identifiers" : []
"message" : " invalid argument " ,
"reason" : " EmptySchedule " ,
"domain" : " api.pushwoosh.com "
Field Type Description resultsarray of NotifyBatchResult One entry per requested item, in request order. succeededinteger Count of items that returned a result. failedinteger Count of items that returned an error.
Field Type Description item_idstring Echo of the request item’s item_id. indexinteger Zero-based position of the item in the request. Use this to correlate results when item_id was left empty. resultobject Set when the item succeeded — same shape as a single Notify response : message_code and unknown_identifiers. errorNotifyBatchErrorSet when the item failed.
Field Type Description codeinteger gRPC status code (google.rpc.Code), e.g. 3 for INVALID_ARGUMENT. messagestring Developer-facing error message, in English. reasonstring Short status name — the same value a single Notify call would return, e.g. EmptySchedule. domainstring Error domain, api.pushwoosh.com.
Errors use the standard gRPC-Gateway error envelope: { "code": ..., "message": ..., "details": [...] }. These are envelope-level errors that fail the whole request — an individual item failing produces a per-item error in results[] instead (see NotifyBatchError above), not one of these.
HTTP status Condition 400items is empty.400items has more than the server-configured limit (500 by default).400One of the items is missing request.
Example
Sending 501 items when the limit is 500 returns HTTP 400:
"message" : " items must not exceed 500 entries, got 501 " ,