Delete Document Files in Batch
Requests the deletion of up to 100 document files in one call and reports an outcome for each file. As with Delete Document File, avoid files of active revisions.
Send the JSON body with this DELETE. If your client omits bodies on DELETE requests, configure it to send the body explicitly.
Files are sorted by documentId, then expectedRevision, and each is handled on its own. A file that does not exist, has a stale expectedRevision, is already being deleted, or cannot be deleted with this key comes back in results as rejected, and the other files proceed. An infrastructure failure stops the run and leaves the remaining files pending.
To continue after an infrastructure failure, or after the call fails as a whole, send the same request again with the same Idempotency-Key. It returns the original batch with the jobs already accepted and retries only the pending files.
This call creates no bulk task.
For the deletion flow, see Delete Documents and Sources.
curl --request DELETE \
--url https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk \
--header 'Authorization: Bearer <token>' \
--header 'Idempotency-Key: <string>' \
--header 'Content-Type: application/json' \
--data '{
"documents": [
{
"documentId": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"expectedRevision": 1
},
{
"documentId": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"expectedRevision": 1
},
{
"documentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"expectedRevision": 1
}
]
}'import requests
url = "https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk"
headers = {
"Authorization": "Bearer <token>",
"Idempotency-Key": "<string>",
"Content-Type": "application/json",
}
payload = {
"documents": [
{
"documentId": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"expectedRevision": 1
},
{
"documentId": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"expectedRevision": 1
},
{
"documentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"expectedRevision": 1
}
]
}
response = requests.request("DELETE", url, headers=headers, json=payload)
print(response.text)const response = await fetch('https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk', {
method: 'DELETE',
headers: {
'Authorization': 'Bearer <token>',
'Idempotency-Key': '<string>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"documents": [
{
"documentId": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"expectedRevision": 1
},
{
"documentId": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"expectedRevision": 1
},
{
"documentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"expectedRevision": 1
}
]
})
});
const data = await response.json();
console.log(data);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_POSTFIELDS => '{
"documents": [
{
"documentId": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"expectedRevision": 1
},
{
"documentId": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"expectedRevision": 1
},
{
"documentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"expectedRevision": 1
}
]
}',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer <token>',
'Idempotency-Key: <string>',
'Content-Type: application/json',
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
url := "https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk"
payload := strings.NewReader("{\n \"documents\": [\n {\n \"documentId\": \"6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b\",\n \"expectedRevision\": 1\n },\n {\n \"documentId\": \"2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b\",\n \"expectedRevision\": 1\n },\n {\n \"documentId\": \"9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a\",\n \"expectedRevision\": 1\n }\n ]\n}")
req, _ := http.NewRequest("DELETE", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Idempotency-Key", "<string>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk"))
.header("Authorization", "Bearer <token>")
.header("Idempotency-Key", "<string>")
.header("Content-Type", "application/json")
.method("DELETE", HttpRequest.BodyPublishers.ofString("{\n \"documents\": [\n {\n \"documentId\": \"6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b\",\n \"expectedRevision\": 1\n },\n {\n \"documentId\": \"2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b\",\n \"expectedRevision\": 1\n },\n {\n \"documentId\": \"9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a\",\n \"expectedRevision\": 1\n }\n ]\n}"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());require 'uri'
require 'net/http'
url = URI('https://api.dify.ai/v1/knowledge-fs/spaces/{knowledge_base_id}/documents/bulk')
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = url.scheme == 'https'
request = Net::HTTP::Delete.new(url)
request['Authorization'] = 'Bearer <token>'
request['Idempotency-Key'] = '<string>'
request['Content-Type'] = 'application/json'
request.body = '{
"documents": [
{
"documentId": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"expectedRevision": 1
},
{
"documentId": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"expectedRevision": 1
},
{
"documentId": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"expectedRevision": 1
}
]
}'
response = http.request(request)
puts response.read_body{
"batch_id": "3e5a7c9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
"items": [
{
"document_id": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"document_title": null,
"job": {
"checkpoint": "requested",
"completed_at": null,
"created_at": "2026-09-06T02:15:30Z",
"error": null,
"id": "b7e1c2d3-4f5a-4b6c-8d9e-0f1a2b3c4d5e",
"knowledge_space_id": "9b2e5b7a-3c1d-4e2f-8a9b-1c2d3e4f5a6b",
"mode": "cascade",
"progress": null,
"retry_at": null,
"run_state": "dispatch_pending",
"target_id": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"target_type": "document",
"updated_at": "2026-09-06T02:15:30Z"
},
"status_url": "https://api.example.com/v1/knowledge-fs/spaces/8d2c6a1e-5b3f-4c7d-9e01-2a3b4c5d6e7f/deletion-jobs/b7e1c2d3-4f5a-4b6c-8d9e-0f1a2b3c4d5e"
},
{
"document_id": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"document_title": null,
"job": {
"checkpoint": "requested",
"completed_at": null,
"created_at": "2026-09-06T02:15:30Z",
"error": null,
"id": "0c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f",
"knowledge_space_id": "9b2e5b7a-3c1d-4e2f-8a9b-1c2d3e4f5a6b",
"mode": "cascade",
"progress": null,
"retry_at": null,
"run_state": "dispatch_pending",
"target_id": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"target_type": "document",
"updated_at": "2026-09-06T02:15:30Z"
},
"status_url": "https://api.example.com/v1/knowledge-fs/spaces/8d2c6a1e-5b3f-4c7d-9e01-2a3b4c5d6e7f/deletion-jobs/0c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f"
}
],
"results": [
{
"document_id": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"error": null,
"job": {
"checkpoint": "requested",
"completed_at": null,
"created_at": "2026-09-06T02:15:30Z",
"error": null,
"id": "b7e1c2d3-4f5a-4b6c-8d9e-0f1a2b3c4d5e",
"knowledge_space_id": "9b2e5b7a-3c1d-4e2f-8a9b-1c2d3e4f5a6b",
"mode": "cascade",
"progress": null,
"retry_at": null,
"run_state": "dispatch_pending",
"target_id": "2c1e7a44-5b6d-4e8f-9a0b-1c2d3e4f5a6b",
"target_type": "document",
"updated_at": "2026-09-06T02:15:30Z"
},
"status": "accepted",
"status_url": "https://api.example.com/v1/knowledge-fs/spaces/8d2c6a1e-5b3f-4c7d-9e01-2a3b4c5d6e7f/deletion-jobs/b7e1c2d3-4f5a-4b6c-8d9e-0f1a2b3c4d5e"
},
{
"document_id": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"error": null,
"job": {
"checkpoint": "requested",
"completed_at": null,
"created_at": "2026-09-06T02:15:30Z",
"error": null,
"id": "0c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f",
"knowledge_space_id": "9b2e5b7a-3c1d-4e2f-8a9b-1c2d3e4f5a6b",
"mode": "cascade",
"progress": null,
"retry_at": null,
"run_state": "dispatch_pending",
"target_id": "6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b",
"target_type": "document",
"updated_at": "2026-09-06T02:15:30Z"
},
"status": "accepted",
"status_url": "https://api.example.com/v1/knowledge-fs/spaces/8d2c6a1e-5b3f-4c7d-9e01-2a3b4c5d6e7f/deletion-jobs/0c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f"
},
{
"document_id": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
"error": {
"code": "DURABLE_DELETION_NOT_FOUND",
"message": "Deletion request was rejected",
"retryable": false
},
"job": null,
"status": "rejected",
"status_url": null
}
],
"status_url": "https://api.example.com/v1/knowledge-fs/spaces/8d2c6a1e-5b3f-4c7d-9e01-2a3b4c5d6e7f/deletion-batches/3e5a7c9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
"total": 3
}{
"code": "knowledge_fs_invalid_request",
"message": "Agent Knowledge Base request is invalid.",
"status": 400,
"violations": [
{
"field": [
"documents"
],
"type": "too_long"
}
]
}{
"code": "knowledge_fs_invalid_request",
"failure": {
"category": "validation",
"code": "KNOWLEDGE_FS_INVALID_REQUEST",
"message": "The Agent Knowledge Base request is invalid.",
"retryPolicy": "never",
"traceId": "7f3c1a90-2e64-4b7d-8a51-6c0d9e2f4b83"
},
"message": "The Agent Knowledge Base request is invalid.",
"status": 400
}{
"code": "knowledge_fs_invalid_credential",
"message": "Invalid Agent Knowledge Base service credential.",
"status": 401
}{
"code": "unauthorized",
"message": "Access token is invalid",
"status": 401
}{
"code": "forbidden",
"message": "Sorry, you have reached the knowledge base request rate limit of your subscription.",
"status": 403
}{
"code": "knowledge_fs_access_denied",
"message": "Agent Knowledge Base operation is not allowed.",
"status": 403
}{
"code": "knowledge_fs_access_denied",
"failure": {
"action": "contact_admin",
"category": "authorization",
"code": "KNOWLEDGE_FS_ACCESS_DENIED",
"message": "You do not have permission to perform this Agent Knowledge Base operation.",
"retryPolicy": "never",
"traceId": "7f3c1a90-2e64-4b7d-8a51-6c0d9e2f4b83"
},
"message": "You do not have permission to perform this Agent Knowledge Base operation.",
"status": 403
}{
"code": "knowledge_fs_resource_not_found",
"failure": {
"category": "not_found",
"code": "KNOWLEDGE_FS_NOT_FOUND",
"message": "The requested Agent Knowledge Base resource was not found.",
"retryPolicy": "never",
"traceId": "7f3c1a90-2e64-4b7d-8a51-6c0d9e2f4b83"
},
"message": "The requested Agent Knowledge Base resource was not found.",
"status": 404
}{
"code": "not_found",
"message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
"status": 404
}{
"code": "knowledge_fs_conflict",
"failure": {
"category": "conflict",
"code": "DURABLE_DELETION_IDEMPOTENCY_CONFLICT",
"message": "The Agent Knowledge Base operation conflicts with the current resource state.",
"retryPolicy": "never",
"traceId": "5e2a9c17-3b4d-4f60-8a1b-2c3d4e5f6a7b"
},
"message": "The Agent Knowledge Base operation conflicts with the current resource state.",
"status": 409
}{
"code": "knowledge_fs_request_too_large",
"message": "Agent Knowledge Base request is too large.",
"status": 413
}{
"code": "knowledge_fs_upstream_unavailable",
"failure": {
"action": "contact_admin",
"category": "internal",
"code": "KNOWLEDGE_FS_INTERNAL_ERROR",
"message": "Agent Knowledge Base could not complete the operation. Try again, or contact an administrator with the error reference.",
"retryPolicy": "manual",
"traceId": "5e2a9c17-3b4d-4f60-8a1b-2c3d4e5f6a7b"
},
"message": "Agent Knowledge Base could not complete the operation. Try again, or contact an administrator with the error reference.",
"status": 502
}{
"code": "knowledge_fs_upstream_unavailable",
"message": "Agent Knowledge Base is unavailable.",
"status": 502
}{
"code": "knowledge_fs_operation_unavailable",
"message": "Agent Knowledge Base operation is not available.",
"status": 503
}{
"code": "knowledge_fs_operation_unavailable",
"failure": {
"action": "retry",
"category": "dependency",
"code": "KNOWLEDGE_FS_UNAVAILABLE",
"message": "A service required by Agent Knowledge Base is temporarily unavailable.",
"retryPolicy": "manual",
"traceId": "5e2a9c17-3b4d-4f60-8a1b-2c3d4e5f6a7b"
},
"message": "A service required by Agent Knowledge Base is temporarily unavailable.",
"status": 503
}Authorization
Every request authenticates with an API key: Authorization: Bearer {API_KEY}. App endpoints take an app API key; knowledge endpoints take a knowledge base API key (Get Started).
Keep keys server-side; never embed them in client code. Requests with a missing or invalid key fail with HTTP 401 (unauthorized).
Path parameters
…/knowledge-fs/spaces/<knowledge base ID>), and the segment after /datasets/new/ in the address bar.Headers
pending files. Reusing the key for a different request, or from another API key, answers 409. Use printable ASCII characters without leading or trailing whitespace.Length: 8–255
Body
application/jsondocumentId must appear once. A larger batch answers 400. The deployment may set a lower cap.Items: 1–100
Show child attributesHide child attributes
version, from List Document Files or Get Document File. A document file's version is always 1. Not the revision number from List Document Revisions.Range: >= 1
Responses
The batch was recorded. results gives each file's outcome, and items lists the accepted files. Deletion runs in the background. Get Document File answers 404 from the moment a file's deletion is accepted. To follow every file to the end, poll Get Deletion Batch (the batch status_url).
Poll the returned job IDs. To retry files left pending, send the same request again with the same Idempotency-Key.
Show child attributesHide child attributes
null for document file deletions.Show child attributesHide child attributes
requested (newly accepted), then quiescing, deleting_objects, deleting_derived_data, deleting_primary_data, and completed.null until then, and on a failed job.null when there is none. It is also set while run_state is retry_wait, so read run_state, not error, to tell whether the job failed.cascade deletes them, keep keeps them. Ignore it on a deletion of a document file or a document.null.null when none is scheduled.Scheduler state:
dispatch_pending(newly accepted),queued,running: in progress.retry_wait: an automatic retry is scheduled atretry_at.completed: everything was removed.failed: cleanup stopped, and the target stays hidden. It can't be retried.
document, the document ID for logical_document, the source ID for source.document for a document file, logical_document for a whole document, source for a source.Show child attributesHide child attributes
null otherwise.status is accepted. null otherwise.Show child attributesHide child attributes
requested (newly accepted), then quiescing, deleting_objects, deleting_derived_data, deleting_primary_data, and completed.null until then, and on a failed job.null when there is none. It is also set while run_state is retry_wait, so read run_state, not error, to tell whether the job failed.cascade deletes them, keep keeps them. Ignore it on a deletion of a document file or a document.null.null when none is scheduled.Scheduler state:
dispatch_pending(newly accepted),queued,running: in progress.retry_wait: an automatic retry is scheduled atretry_at.completed: everything was removed.failed: cleanup stopped, and the target stays hidden. It can't be retried.
document, the document ID for logical_document, the source ID for source.document for a document file, logical_document for a whole document, source for a source.accepted: deletion was accepted, andjobandstatus_urlare set.rejected: the file was not deleted.errorsays why.pending: the file was not accepted yet. To retry it, send the original request again with the sameIdempotency-Key.
SERVICE_API_URL, otherwise a path that starts with /v1/. Delete Document Files in Batch also sends it in the Location response header.