HTTP 207 Multi-Status is a WebDAV extension (RFC 4918) that conveys information about multiple resources in situations where multiple status codes might be appropriate. The response body is an XML document containing individual status codes for each sub-operation. This is used when a single request affects multiple resources — like batch operations — and some succeed while others fail. The overall 207 status means 'look inside the body for individual results.'
Response includes the status code, standard headers (including Content-Type), and a small diagnostic JSON body describing the request and returned status.
Simulator URL (copy in the app after load — not a normal link):
https://httpstatus.com/api/status/207
Example request:
curl -i "https://httpstatus.com/api/status/207"Provides status for multiple independent operations (WebDAV). The response body contains XML with status information for each operation.
On this code, Inspector focuses on semantics, headers, and correctness warnings that commonly affect clients and caches.
207 Multi-Status (RFC 4918 Section 13) uses an XML body with a <multistatus> root element containing <response> elements, each with an <href> (the affected resource) and a <status> (the HTTP status line for that resource). This allows a single PROPFIND, PROPPATCH, or COPY operation on a collection to report per-resource outcomes. While originating in WebDAV, modern REST APIs adopt the concept for batch endpoints using JSON: POST /api/batch returns 207 with an array of results, each containing its own status code. Key: the overall 207 status does NOT imply all sub-operations succeeded — the client MUST inspect each individual result.
app.post('/api/batch', async (req, res) => {
const results = await Promise.all(
req.body.operations.map(async (op, index) => {
try {
const result = await processOperation(op);
return { index, status: 200, data: result };
} catch (err) {
return { index, status: err.statusCode || 500,
error: err.message };
}
})
);
res.status(207).json({ results });
});@app.post('/api/batch', status_code=207)
async def batch_operations(ops: List[Operation]):
results = []
for i, op in enumerate(ops):
try:
data = await process_op(op)
results.append({'index': i, 'status': 200, 'data': data})
except AppError as e:
results.append({'index': i, 'status': e.code, 'error': str(e)})
return {'results': results}@PostMapping("/api/batch")
public ResponseEntity<BatchResponse> batch(
@RequestBody List<Operation> ops) {
List<BatchResult> results = ops.stream()
.map(op -> {
try {
Object data = processOp(op);
return new BatchResult(200, data, null);
} catch (AppException e) {
return new BatchResult(e.getStatus(), null, e.getMessage());
}
}).toList();
return ResponseEntity.status(207).body(new BatchResponse(results));
}func batchHandler(w http.ResponseWriter, r *http.Request) {
var ops []Operation
json.NewDecoder(r.Body).Decode(&ops)
results := make([]BatchResult, len(ops))
for i, op := range ops {
data, err := processOp(op)
if err != nil {
results[i] = BatchResult{Status: 500, Error: err.Error()}
} else {
results[i] = BatchResult{Status: 200, Data: data}
}
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(207)
json.NewEncoder(w).Encode(map[string]any{"results": results})
}