REST API Bulk Endpoint Example
For a homogeneous operation such as creating customers, a dedicated bulk endpoint is easier to validate and authorize than a generic endpoint that accepts arbitrary HTTP requests.
POST /v1/customers/bulk HTTP/1.1
Content-Type: application/json
Idempotency-Key: "bulk-customer-import-2026-10-06-001"
{
"items": [
{"client_ref":"row-1","name":"Northwind","email":"ops@northwind.example"},
{"client_ref":"row-2","name":"Contoso","email":"ops@contoso.example"}
]
}A client reference is useful because array position alone can become awkward when requests are split, retried or transformed. The server should also enforce a maximum item count and overall request size.
REST API Bulk Response Example
For a non-atomic batch, return a result for every submitted item:
HTTP/1.1 200 OK
Content-Type: application/json
{
"summary": {
"submitted": 2,
"succeeded": 1,
"failed": 1
},
"results": [
{
"client_ref": "row-1",
"status": "succeeded",
"resource": {"id":"cus_901","href":"/v1/customers/cus_901"}
},
{
"client_ref": "row-2",
"status": "failed",
"error": {
"code": "EMAIL_ALREADY_EXISTS",
"message": "A customer with this email already exists."
}
}
]
}The top-level HTTP status describes the bulk request as a whole; per-item fields describe individual outcomes. Document this distinction clearly so clients do not treat a 200 response as “every item succeeded.”
Bulk Response Contract: Preserve Item Correlation
A bulk response should make it possible to reconcile every accepted input without relying on array order. Echo a safe client reference or return a server-generated item identifier so clients can retry or correct only the failed subset.
200 OK envelope can still contain failed items. Make the summary and every per-item outcome explicit, and document whether omitted items are possible.Atomic Bulk Request vs Partial Success
Atomic batch
Either every item is committed or none are. Useful when the set must remain consistent, but large transactions can increase lock time and failure blast radius.
Partial-success batch
Each item is processed independently. Better throughput and fault isolation, but the response and retry model must identify exactly which items succeeded.
Do not leave atomicity ambiguous. A client that retries the entire request after one item fails can create duplicates unless the API defines idempotency or item-level deduplication.
Which HTTP Status Code Should a Bulk API Return?
There is no single HTTP status code that standardizes all bulk API semantics. Choose a top-level status based on the bulk request contract and put item-level outcomes in the representation.
| Situation | Possible top-level status | Notes |
|---|---|---|
| Request malformed before item processing | 400 Bad Request | Batch envelope cannot be parsed or validated. |
| Authentication/authorization fails for whole operation | 401 / 403 | Do not process items if the bulk action itself is unauthorized. |
| Non-atomic batch processed with mixed item outcomes | 200 OK | Common design when the body contains per-item success/failure. |
| Large batch accepted for background processing | 202 Accepted | Return operation/status URL. |
| All items created synchronously | 201 Created or 200 OK | Document whether one or many resource links are returned. |
207 Multi-Status exists in WebDAV, but it is not automatically the best choice for general JSON APIs. Use it only if your API intentionally adopts and documents those semantics; a normal 200 response with explicit per-item results is often simpler for non-WebDAV clients.
207 Multi-Status is defined by WebDAV rather than as a general-purpose “partial success” status for arbitrary JSON APIs. If your API is not using WebDAV semantics, a documented 200/202 envelope with per-item results is usually easier for clients to interpret consistently.
When a Bulk Endpoint Should Become Asynchronous
Move large or expensive batches into an asynchronous job when synchronous processing would exceed normal latency budgets, hold long database transactions, or create gateway timeout risk.
HTTP/1.1 202 Accepted
Location: /v1/operations/op_bulk_81
{
"operation_id": "op_bulk_81",
"status": "queued",
"submitted_items": 5000
}The eventual result can be paginated if it contains thousands of per-item outcomes. See async API job status endpoint examples and REST API pagination examples.
Bulk API Retries and Idempotency
Retries are especially dangerous for partial-success batches because the client may not know how many items committed before a timeout. Use a request-level idempotency key, item-level stable client references, or both.
- Request-level idempotency prevents a complete replay of one logical batch from applying again.
- Item-level idempotency lets clients retry only failed or uncertain items.
- A reused key with different items should be rejected, not interpreted as an update to the old batch.
- For long-running batches, the idempotency record can point to the original operation resource.
Bulk Endpoint Security and Resource Limits
- Set a maximum item count and maximum request body size.
- Validate every item independently as well as the batch envelope.
- Authorize every target object/action; bulk access is not a shortcut around object-level authorization.
- Limit aggregate work such as total uploaded bytes, total objects touched or total query cost.
- Avoid returning sensitive data for successful items merely because the request is bulk.
- Rate-limit by logical work units in addition to raw HTTP request count. A single bulk request can represent thousands of operations.
Bulk endpoints can magnify abuse. Runtime behavior should be evaluated alongside normal rate-limiting and API abuse detection.
For item-level body constraints, see REST API request validation examples and best practices.
Common Bulk API Design Mistakes
- Accepting unlimited arrays because “it is only one HTTP request.”
- Returning one generic error with no way to identify which item failed.
- Allowing partial success without an idempotent retry strategy.
- Using array index as the only durable correlation identifier.
- Holding a huge database transaction open for an entire batch by default.
- Returning 200 with a body whose mixed-success semantics are undocumented.
Prefer Homogeneous Bulk Endpoints over Arbitrary Batch RPC
A generic endpoint that accepts a list of arbitrary method/URL/body triples can reduce network round trips, but it also multiplies authorization, ordering, dependency and error-handling complexity. When the real use case is “create many customers” or “update many inventory records,” a homogeneous bulk endpoint is usually easier to secure and document.
# Easier to constrain
POST /v1/inventory/bulk-adjustments
{ "items": [ ...same operation shape... ] }
# Much harder to reason about
POST /v1/batch
{ "requests": [
{"method":"DELETE","url":"/users/1"},
{"method":"POST","url":"/payments", "body":{...}}
] }If arbitrary batching is truly required, authorize each subrequest exactly as if it arrived independently and define whether one subrequest can reference the result of another. Do not assume authentication of the outer batch grants permission to every inner operation.
Designing Per-Item Bulk Errors for Automation
Per-item errors should be machine-actionable. Include a stable code, a human-readable message, and the submitted correlation reference. For validation errors, include field details where useful. Avoid forcing clients to parse English text to decide which items can be corrected and retried.
{
"client_ref":"row-17",
"status":"failed",
"error": {
"code":"VALIDATION_ERROR",
"message":"One or more fields are invalid",
"fields":[
{"field":"email","code":"format"}
],
"retryable": false
}
}If you add a retryable hint, treat it as part of the public contract and set it from known error semantics—not by assuming every server-side failure is safe to replay.
How Ammune Fits
Bulk endpoints compress a large amount of business activity into a small number of HTTP requests, so request count alone can understate risk. Ammune can add runtime visibility into payload size, endpoint behavior, usage patterns and anomalous high-volume operations while the application enforces per-item authorization and transactional rules.
Production Implementation Checklist
- Use a dedicated homogeneous bulk endpoint where practical.
- Set maximum item count, request bytes and aggregate work.
- Require a client correlation reference for each item.
- Document atomic vs partial-success semantics.
- Return a per-item result for every accepted item.
- Use stable machine-readable error codes.
- Define request-level and/or item-level idempotency.
- Authorize every item independently.
- Use 202 + operation resource for large asynchronous batches.
- Rate-limit based on logical work, not only HTTP request count.
Frequently Asked Questions
How should a REST API bulk endpoint be designed?
Use a dedicated operation with a bounded items array, explicit maximums, item correlation identifiers, documented atomicity, and a response that reports every item outcome.
What should a REST API bulk response look like?
A useful response contains a top-level summary plus a result entry for each submitted item, including the client reference, success resource or structured error.
What status code should a bulk API return for partial success?
There is no universal status for general bulk JSON APIs. Many APIs return 200 for a successfully processed batch envelope and represent per-item success/failure in the body. Whatever you choose must be documented consistently.
Should bulk operations be atomic?
Only when the business requirement needs all-or-nothing behavior and the batch size makes that practical. Partial-success processing is often more scalable but requires a stronger retry and response model.
How do I retry a failed bulk API request safely?
Use request-level or item-level idempotency and stable item identifiers. Do not blindly resend a partially successful batch unless the API contract guarantees safe deduplication.
Primary References
Understand the Real Work Behind Bulk API Calls
Bulk APIs can hide thousands of logical operations inside one request. Runtime API visibility helps security and operations teams see that workload in context.
