Delete Document
Permanently delete a document and all associated data
Permanently delete a document and all its associated data including the original file, extracted data, and metadata.
/v1/documents/:idOverview
Use this endpoint to:
- Remove sensitive documents after processing
- Clean up failed or test documents
- Comply with data retention policies
- Free up storage (for enterprise plans)
Permanent Deletion
This action is irreversible. Once deleted, the document and all its data cannot be recovered. Credits used for processing are not refunded.
Request
Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Keyrequired | string | Your DocuRift API key (format: frc_xxxxx) |
Path Parameters
| Parameter | Type | Description |
|---|---|---|
idrequired | string | Document ID to delete (format: doc_xxxxx) |
Code Examples
cURL
curl -X DELETE "https://api.docurift.com/v1/documents/doc_abc123xyz456" \
-H "X-API-Key: frc_your_api_key_here"Python
import requests
import os
API_KEY = os.getenv('DOCURIFT_API_KEY')
API_URL = 'https://api.docurift.com/v1'
def delete_document(document_id):
"""Delete a document permanently."""
headers = {
'X-API-Key': API_KEY
}
response = requests.delete(
f'{API_URL}/documents/{document_id}',
headers=headers
)
response.raise_for_status()
return response.json()
# Example usage
result = delete_document('doc_abc123xyz456')
if result['success']:
print(f"Document deleted successfully")
print(f"Deleted at: {result['data']['deletedAt']}")JavaScript
const API_KEY = process.env.DOCURIFT_API_KEY;
const API_URL = 'https://api.docurift.com/v1';
async function deleteDocument(documentId) {
const response = await fetch(`${API_URL}/documents/${documentId}`, {
method: 'DELETE',
headers: {
'X-API-Key': API_KEY
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
return response.json();
}
// Example usage
try {
const result = await deleteDocument('doc_abc123xyz456');
console.log('Document deleted:', result.data.id);
console.log('Deleted at:', result.data.deletedAt);
} catch (error) {
console.error('Failed to delete:', error.message);
}Batch Delete (Python)
import requests
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
API_KEY = os.getenv('DOCURIFT_API_KEY')
API_URL = 'https://api.docurift.com/v1'
def delete_document(document_id):
"""Delete a single document."""
headers = {'X-API-Key': API_KEY}
response = requests.delete(f'{API_URL}/documents/{document_id}', headers=headers)
response.raise_for_status()
return document_id
def batch_delete_documents(document_ids, max_workers=5):
"""
Delete multiple documents in parallel.
Args:
document_ids: List of document IDs to delete
max_workers: Maximum concurrent deletions
Returns:
dict with successful and failed deletions
"""
results = {'deleted': [], 'failed': []}
with ThreadPoolExecutor(max_workers=max_workers) as executor:
future_to_id = {
executor.submit(delete_document, doc_id): doc_id
for doc_id in document_ids
}
for future in as_completed(future_to_id):
doc_id = future_to_id[future]
try:
future.result()
results['deleted'].append(doc_id)
except Exception as e:
results['failed'].append({'id': doc_id, 'error': str(e)})
return results
# Example: Delete all failed documents
def delete_failed_documents():
"""Delete all documents with failed status."""
headers = {'X-API-Key': API_KEY}
# Get all failed documents
response = requests.get(
f'{API_URL}/documents?status=failed&limit=100',
headers=headers
)
response.raise_for_status()
failed_docs = response.json()['data']['documents']
doc_ids = [doc['id'] for doc in failed_docs]
if doc_ids:
results = batch_delete_documents(doc_ids)
print(f"Deleted {len(results['deleted'])} documents")
if results['failed']:
print(f"Failed to delete {len(results['failed'])} documents")
else:
print("No failed documents to delete")Response
Success Response (200 OK)
{
"success": true,
"data": {
"id": "doc_abc123xyz456",
"deleted": true,
"deletedAt": "2024-01-26T12:00:00Z"
},
"message": "Document and all associated data have been permanently deleted"
}Response Fields
| Parameter | Type | Description |
|---|---|---|
id | string | ID of the deleted document |
deleted | boolean | Confirmation of deletion (always true on success) |
deletedAt | string | ISO 8601 timestamp of deletion |
Error Responses
401 Unauthorized
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid API key"
}
}403 Forbidden
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "You do not have permission to delete this document"
}
}404 Not Found
{
"success": false,
"error": {
"code": "DOCUMENT_NOT_FOUND",
"message": "Document with ID 'doc_abc123xyz456' not found"
}
}409 Conflict
{
"success": false,
"error": {
"code": "DOCUMENT_PROCESSING",
"message": "Cannot delete document while it is being processed. Wait for processing to complete or cancel first."
}
}Error Codes Reference
| Code | HTTP Status | Description | Solution |
|------|-------------|-------------|----------|
| INVALID_API_KEY | 401 | API key invalid or expired | Verify API key |
| FORBIDDEN | 403 | No permission to delete | Check organization access |
| DOCUMENT_NOT_FOUND | 404 | Document does not exist | Verify document ID |
| DOCUMENT_PROCESSING | 409 | Document is being processed | Wait for completion |
Best Practices
Confirm Before Deletion
Always verify the document before deletion in production:
def safe_delete_document(document_id, confirm=True):
"""Delete with confirmation."""
# First, get the document to verify
headers = {'X-API-Key': API_KEY}
response = requests.get(f'{API_URL}/documents/{document_id}', headers=headers)
if response.status_code == 404:
print(f"Document {document_id} not found")
return None
doc = response.json()['data']
if confirm:
print(f"About to delete:")
print(f" ID: {doc['id']}")
print(f" File: {doc['fileName']}")
print(f" Type: {doc['documentType']}")
print(f" Status: {doc['status']}")
confirmation = input("Type 'DELETE' to confirm: ")
if confirmation != 'DELETE':
print("Deletion cancelled")
return None
return delete_document(document_id)Implement Soft Delete Pattern
For applications requiring undo functionality, implement soft delete:
// Store deleted document IDs with metadata before deletion
const deletedDocuments = new Map();
const RETENTION_PERIOD = 30 * 24 * 60 * 60 * 1000; // 30 days
async function softDelete(documentId) {
// Get document data first
const doc = await getDocument(documentId);
// Store in soft delete registry
deletedDocuments.set(documentId, {
metadata: doc.data,
deletedAt: new Date(),
expiresAt: new Date(Date.now() + RETENTION_PERIOD)
});
// Actually delete from DocuRift
await deleteDocument(documentId);
console.log(`Document ${documentId} soft-deleted. Metadata retained for 30 days.`);
}
// Clean up expired soft-deleted records
function cleanupExpired() {
const now = Date.now();
for (const [id, data] of deletedDocuments) {
if (data.expiresAt < now) {
deletedDocuments.delete(id);
}
}
}Audit Logging
Log all delete operations for compliance:
import logging
from datetime import datetime
# Configure audit logger
audit_logger = logging.getLogger('docurift.audit')
audit_logger.setLevel(logging.INFO)
def audited_delete(document_id, user_id, reason=None):
"""Delete with audit logging."""
# Log before deletion
audit_logger.info(
f"DELETE_INITIATED | doc_id={document_id} | user={user_id} | reason={reason}"
)
try:
result = delete_document(document_id)
audit_logger.info(
f"DELETE_SUCCESS | doc_id={document_id} | user={user_id} | "
f"deleted_at={result['data']['deletedAt']}"
)
return result
except Exception as e:
audit_logger.error(
f"DELETE_FAILED | doc_id={document_id} | user={user_id} | error={str(e)}"
)
raiseData Retention Policy
Implement automated cleanup based on retention policy:
from datetime import datetime, timedelta
def cleanup_old_documents(retention_days=90, dry_run=True):
"""
Delete documents older than retention period.
Args:
retention_days: Number of days to retain documents
dry_run: If True, only report what would be deleted
"""
cutoff_date = datetime.utcnow() - timedelta(days=retention_days)
# Get old documents
result = list_documents(
end_date=cutoff_date.isoformat() + 'Z',
status='completed',
limit=100
)
documents = result['data']['documents']
if dry_run:
print(f"[DRY RUN] Would delete {len(documents)} documents:")
for doc in documents:
print(f" - {doc['id']}: {doc['fileName']} ({doc['createdAt']})")
return
# Delete old documents
deleted_count = 0
for doc in documents:
try:
delete_document(doc['id'])
deleted_count += 1
except Exception as e:
print(f"Failed to delete {doc['id']}: {e}")
print(f"Deleted {deleted_count} documents older than {retention_days} days")Credits
Deleting a document does not refund the credits used for processing. Credits are consumed at the time of processing.
Processing Documents
You cannot delete a document that is currently being processed. Wait for processing to complete or fail before attempting deletion.
Related Endpoints
- Get Document - Retrieve before deleting
- List Documents - Find documents to delete
- Process Document - Upload new documents