---
title: "Batch Delete Documents"
method: DELETE
path: "/v1/collections/{collection_identifier}/documents/batch"
tags: ["Collection Documents"]
---

# Batch Delete Documents

`DELETE /v1/collections/{collection_identifier}/documents/batch`

## Request

- Base URL: `https://api.mixpeek.com`
- URL: `https://api.mixpeek.com/v1/collections/{collection_identifier}/documents/batch`
- Auth: HTTP bearer and API key in header `X-Namespace`

Batch delete multiple documents by explicit IDs or filters.

Supports TWO modes:
1. Explicit IDs mode: Provide 'document_ids' array
   - Deletes specific documents by ID
   - Returns detailed per-document results
   - Maximum 1000 documents per batch

2. Filter mode: Provide 'filters' to delete all matching documents
   - Deletes ALL documents matching the filters
   - Returns total count only
   - Use with caution - can delete many documents

Key Features:
- Per-document success/failure reporting in explicit mode
- Validates documents exist in the specified collection
- Automatic document count update for the collection
- Efficient bulk deletion

Examples:
    Explicit IDs mode:
    ```json
    {
        "document_ids": ["doc_123", "doc_456", "doc_789"]
    }
    ```

    Filter mode (logical AND/OR/NOT shape — NOT MVS-native must/key):
    ```json
    {
        "filters": {"AND": [{"field": "metadata.status", "operator": "eq", "value": "archived"}]}
    }
    ```

## Path parameters

- `collection_identifier` string, required: The ID of the collection to delete documents from.

## Request body

- BatchDeleteDocumentsRequest: Request model for batch deleting multiple documents by explicit IDs or filters. Supports TWO modes: 1. Explicit IDs mode: Provide 'document_ids' array 2. Filter mode: Provide 'filters' to delete all matching documents Use Cases: - Delete 5 specific documents in one API call - Delete all documents matching criteria - Bulk cleanup operations Requirements: - EITHER 'document_ids' OR 'filters' must be provided - NOT BOTH modes simultaneously
  - `document_ids` string[], nullable: OPTIONAL. List of document IDs to delete. Use this mode when you know exact document IDs to delete. Mutually exclusive with filters mode. Maximum 1000 documents per batch request.
  - `filters` LogicalOperatorInput: Represents a logical operation (AND, OR, NOT) on filter conditions. Allows nesting with a defined depth limit. Also supports shorthand syntax where field names can be passed directly as key-value pairs for equality filtering (e.g., {"metadata.title": "value"}).
    - `AND` union[], nullable: Logical AND operation - all conditions must be true
      - union
        - LogicalOperatorInput (recursive)
        - FilterCondition: Represents a single filter condition. Attributes: field: The field to filter on operator: The comparison operator value: The value to compare against
          - `field` string, required: Field name to filter on
          - `operator` 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'contains' | 'starts_with' | 'ends_with' | 'regex' | 'exists' | 'is_null' | 'text' | 'phrase' | 'words' | 'geo_radius' | 'geo_bounding_box' | 'geo_polygon': Supported filter operators across database implementations. `text` is a case-insensitive substring match on the MVS vector store, in the in-memory evaluator and in the collections list filter; it does not tokenize or rank. On the Mongo query translator it becomes a Mongo `$text` search, which needs a collection text index and searches every indexed field. For whole-word matching on one field use `words`: every word of the value must appear as a whole word, compared on its English stem.
          - `value` union, required: Value to compare against
            - DynamicValue: A value that should be dynamically resolved from the query request.
              - …
            - unknown
    - `OR` union[], nullable: Logical OR operation - at least one condition must be true
      - union
        - LogicalOperatorInput (recursive)
        - FilterCondition: Represents a single filter condition. Attributes: field: The field to filter on operator: The comparison operator value: The value to compare against
          - `field` string, required: Field name to filter on
          - `operator` 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'contains' | 'starts_with' | 'ends_with' | 'regex' | 'exists' | 'is_null' | 'text' | 'phrase' | 'words' | 'geo_radius' | 'geo_bounding_box' | 'geo_polygon': Supported filter operators across database implementations. `text` is a case-insensitive substring match on the MVS vector store, in the in-memory evaluator and in the collections list filter; it does not tokenize or rank. On the Mongo query translator it becomes a Mongo `$text` search, which needs a collection text index and searches every indexed field. For whole-word matching on one field use `words`: every word of the value must appear as a whole word, compared on its English stem.
          - `value` union, required: Value to compare against
            - DynamicValue: A value that should be dynamically resolved from the query request.
              - …
            - unknown
    - `NOT` union[], nullable: Logical NOT operation - all conditions must be false
      - union
        - LogicalOperatorInput (recursive)
        - FilterCondition: Represents a single filter condition. Attributes: field: The field to filter on operator: The comparison operator value: The value to compare against
          - `field` string, required: Field name to filter on
          - `operator` 'eq' | 'ne' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'contains' | 'starts_with' | 'ends_with' | 'regex' | 'exists' | 'is_null' | 'text' | 'phrase' | 'words' | 'geo_radius' | 'geo_bounding_box' | 'geo_polygon': Supported filter operators across database implementations. `text` is a case-insensitive substring match on the MVS vector store, in the in-memory evaluator and in the collections list filter; it does not tokenize or rank. On the Mongo query translator it becomes a Mongo `$text` search, which needs a collection text index and searches every indexed field. For whole-word matching on one field use `words`: every word of the value must appear as a whole word, compared on its English stem.
          - `value` union, required: Value to compare against
            - DynamicValue: A value that should be dynamically resolved from the query request.
              - …
            - unknown
    - `case_sensitive` boolean, nullable: Whether to perform case-sensitive matching
  - `reason` string, nullable: OPTIONAL. Why this bulk delete is happening — recorded on the DOCUMENT_BULK_SOFT_DELETED audit event so a document-level wipe carries the caller's own context, not just the actor and counts.

## Response `200`

Successful Response

- BatchDeleteDocumentsResponse: Response model for batch document delete operation. Two shapes, keyed on the request mode: - Explicit IDs mode is SYNCHRONOUS and fast (targets point ids directly): deleted_count / failed_count / results are populated, task_id is null. - Filter mode is ASYNC: it scrolls matches on the shard, which can exceed a request's connection window (same cost shape as bulk update), so it enqueues a task and returns task_id + status=PENDING with deleted_count null. Poll GET /v1/tasks/{task_id} for the terminal status and deleted_count.
  - `task_id` string, nullable: Id of the background task for a FILTER-mode delete. Null for explicit-IDs mode (which completes synchronously). Poll GET /v1/tasks/{task_id} for status and the final deleted_count.
  - `status` string, nullable: Task status at enqueue time (PENDING) for a filter-mode delete. Null for the synchronous explicit-IDs mode.
  - `deleted_count` integer, nullable: Total number of documents successfully deleted. Null on the async filter-mode enqueue response; populated on the task record when it completes, and returned synchronously in explicit-IDs mode.
  - `failed_count` integer: Total number of documents that failed to delete
  - `results` BatchDocumentDeleteResult[]: Detailed per-document results. Each entry shows document_id, success status, and error message (if failed). Empty list when using filter mode (only counts returned).
    - `document_id` string, required: Document ID that was deleted
    - `success` boolean, required: Whether the deletion succeeded
    - `error` string, nullable: Error message if deletion failed
  - `limits` object, nullable: Filter mode only: the caps this request ran against. max_rows_inline is the row cap under which a delete by filter runs in the request; matched is how many documents the filter matched when the request arrived. Over the cap the delete runs as a task (task_id).
  - `message` string: Summary message of the operation

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `422`: Unprocessable Entity
- `429`: Too Many Requests
- `500`: Internal Server Error
- `503`: Service Unavailable

## Changes

- **2026-10-09** `61a175e8eb9a`: 1 warning, 5 info
  - removed the optional property `detail` from the response with the `422` status
  - added the non-success response with the status `429`
  - added the non-success response with the status `503`
  - added the optional property `success` to the response with the `422` status
  - …2 more
- **2026-10-04** `38e0822db900`: 1 info
  - added the optional property `limits` to the response with the `200` status
- **2026-09-26** `5231c1d891e8`: 3 info
  - added the new `words` enum value to the request property `filters/anyOf[subschema #1: LogicalOperator]/AND/anyOf[subschema #1]/items/anyOf[subschema #2: FilterCondition]/operator`
  - added the new `words` enum value to the request property `filters/anyOf[subschema #1: LogicalOperator]/NOT/anyOf[subschema #1]/items/anyOf[subschema #2: FilterCondition]/operator`
  - added the new `words` enum value to the request property `filters/anyOf[subschema #1: LogicalOperator]/OR/anyOf[subschema #1]/items/anyOf[subschema #2: FilterCondition]/operator`
- **2026-08-30** `3775e0b36ee1`: 2 breaking, 2 info
  - the response property `deleted_count` became optional for the status `200`
  - response property `deleted_count` list-of-types was widened by adding types `null` to media type `application/json` of response `200`
  - added the optional property `status` to the response with the `200` status
  - added the optional property `task_id` to the response with the `200` status
- …earlier changes not shown

[Operation history](https://skmtc.dev/mixpeek/apis/mixpeek-api/changes/v1/collections/:collection_identifier/documents/batch/delete.md)

---

[API](https://skmtc.dev/mixpeek/apis/mixpeek-api.md) - [All operations](https://skmtc.dev/mixpeek/apis/mixpeek-api/llms.txt) - [OpenAPI document](https://skmtc.dev/mixpeek/apis/mixpeek-api/revisions/790bc16455f6?raw)
