Access Overrides
API reference for requesting and processing document deletion overrides.
Some documents are protected by retention policies or restricted deletableBy settings — DELETE /documents/:id on one of these answers DELETE_BLOCKED (see Documents). To delete it anyway, an operator requests a deletion override; a different Super Admin then approves it (and, for documents under LEGAL or PERMANENT retention, a third Super Admin witnesses it) before it can be executed.
This provides an auditable two- (or three-) person approval flow for sensitive document deletion. The document is deleted by executing the approved override — not by retrying the original DELETE call.
Request a deletion override
POST /api/v1/storage/fixed/overrides
Scope: storage:upload (every /storage/* route requires it when the key has scopes)
Request body
| Field | Type | Required | Description |
|---|---|---|---|
documentId | string | Yes | ID of the document to delete |
overrideReason | string | Yes | Justification for the deletion — minimum 500 characters, for audit and compliance |
authorityReference | string | No | Reference to the authority permitting the override (e.g. a legal case number) |
authorityType | string | No | Type of authority (e.g. COURT_ORDER, LEGAL_COUNSEL) |
authorityDocument | string | No | Reference to a supporting document for the authority |
operatorId | string | No | Caller-scoped identity of the human operator, for four-eyes separation. Always namespaced under your authenticated caller service server-side — it can identify a distinct person for the approve/witness checks below, but can never impersonate another tenant's identity |
Response
{
"success": true,
"data": {
"id": "ovr_abc123",
"documentId": "doc_xyz789",
"documentTitle": "Employment Contract - Ade Bakare",
"overrideReason": "Duplicate contract uploaded in error during the 2026 HR migration. Original contract doc_original456 remains the system of record...",
"authorityReference": null,
"authorityType": null,
"requestedById": "service:lettings:admin_001",
"requestedAt": "2026-04-05T10:00:00.000Z",
"approvedById": null,
"approvedAt": null,
"witnessedById": null,
"witnessedAt": null,
"status": "PENDING",
"rejectionReason": null,
"executedAt": null
}
}
| Field | Type | Description |
|---|---|---|
id | string | Override request ID |
documentId | string | The document targeted for deletion |
documentTitle | string | The document's title at the time of the request |
overrideReason | string | Stated justification |
authorityReference | string or null | Authority reference, if given |
authorityType | string or null | Authority type, if given |
requestedById | string | Identity of the requester — service:<callerService> or service:<callerService>:<operatorId> |
requestedAt | string | ISO 8601 request timestamp |
approvedById | string or null | Approver identity, once approved or rejected |
approvedAt | string or null | ISO 8601 approval/rejection timestamp |
witnessedById | string or null | Witness identity, once witnessed |
witnessedAt | string or null | ISO 8601 witness timestamp |
status | string | PENDING, APPROVED, REJECTED, or EXECUTED |
rejectionReason | string or null | Not currently populated by the API (reserved) |
executedAt | string or null | Not currently populated by the API (reserved) — check status === "EXECUTED" instead |
Process a deletion override
PATCH /api/v1/storage/fixed/overrides/:overrideId
Scope: storage:upload (every /storage/* route requires it when the key has scopes)
One endpoint, four actions. Approve and witness must each be performed by a different Super Admin than the requester (and, for witness, than the approver too) — the API rejects self-approval and self-witnessing.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | approve, reject, witness, or execute |
rejectionReason | string | Only for action: "reject" | Reason for rejecting the request |
operatorId | string | No | Same caller-scoped operator identity as the request step, for four-eyes separation |
approve / reject / witness response
Same shape as the POST response above, reflecting the new status (APPROVED/REJECTED) or the recorded witnessedById/witnessedAt (witnessing does not change status — it stays APPROVED).
execute response
Different shape. Executing performs the soft-delete directly — there's no need to retry DELETE /documents/:documentId afterward.
{
"success": true,
"data": {
"success": true,
"documentId": "doc_xyz789"
}
}
Override workflow
1. Operator attempts DELETE /documents/:id
-> 403 DELETE_BLOCKED (document is retention-protected)
2. Operator requests an override
POST /overrides { documentId, overrideReason }
-> status: PENDING
3. A DIFFERENT Super Admin approves it
PATCH /overrides/:id { action: "approve" }
-> status: APPROVED
4. Only if the document's retentionType is LEGAL or PERMANENT:
a THIRD Super Admin (not the requester or approver) witnesses it
PATCH /overrides/:id { action: "witness" }
-> witnessedById / witnessedAt recorded (status stays APPROVED)
5. Execute the override — this performs the deletion
PATCH /overrides/:id { action: "execute" }
-> { success: true, documentId } — the document is now soft-deleted,
and the override's status becomes EXECUTED
Examples
Request, approve, and execute an override
curl
# Step 1: Request override
curl -X POST https://api.platformxe.com/api/v1/storage/fixed/overrides \
-H "Content-Type: application/json" \
-H "x-api-key: pxk_live_your_api_key_here" \
-d '{
"documentId": "doc_xyz789",
"overrideReason": "Duplicate contract uploaded in error during the 2026 HR migration. Original contract doc_original456 remains the system of record. Confirmed with HR lead on 2026-04-05. This satisfies the 500-character minimum required for the audit trail on deletion overrides for retention-protected documents."
}'
# Step 2: A different Super Admin approves it
curl -X PATCH https://api.platformxe.com/api/v1/storage/fixed/overrides/ovr_abc123 \
-H "Content-Type: application/json" \
-H "x-api-key: pxk_live_your_api_key_here" \
-d '{ "action": "approve" }'
# Step 3: Execute — this deletes the document
curl -X PATCH https://api.platformxe.com/api/v1/storage/fixed/overrides/ovr_abc123 \
-H "Content-Type: application/json" \
-H "x-api-key: pxk_live_your_api_key_here" \
-d '{ "action": "execute" }'
TypeScript SDK
import { PlatformXeClient } from '@caldera/platformxe-sdk';
const px = new PlatformXeClient({ apiKey: 'pxk_live_your_api_key_here' });
// Request override
const override = await px.documents.requestOverride({
documentId: 'doc_xyz789',
overrideReason: 'Duplicate contract uploaded in error... (500+ characters)',
});
console.log(override.status);
// "PENDING"
// A different Super Admin approves it
const approved = await px.documents.processOverride(override.id, {
action: 'approve',
});
console.log(approved.status);
// "APPROVED"
// Execute — deletes the document as part of this call
const result = await px.documents.executeOverride(override.id);
console.log(result.success, result.documentId);
// true "doc_xyz789"
Python SDK
from platformxe import PlatformXeClient
px = PlatformXeClient(api_key="pxk_live_your_api_key_here")
# Request override
override = px.documents.request_override(
document_id="doc_xyz789",
override_reason="Duplicate contract uploaded in error... (500+ characters)",
)
# A different Super Admin approves it
px.documents.process_override(override["id"], action="approve")
# Execute — deletes the document as part of this call
result = px.documents.process_override(override["id"], action="execute")
print(result["success"], result["documentId"])
# True "doc_xyz789"
Reject an override
await px.documents.processOverride('ovr_abc123', {
action: 'reject',
rejectionReason: 'This contract is still active, cannot delete',
});
Error responses
| Code | Status | Description |
|---|---|---|
BAD_REQUEST | 400 | Missing documentId/overrideReason on request, or missing action on process |
VALIDATION_ERROR | 400 | overrideReason is shorter than the required 500-character minimum |
FORBIDDEN | 403 | The API key has scopes but not storage:upload (required on every /storage/* route), the key's organization is inactive, or the approver/witness is the same identity as the requester (or, for witness, the approver). Identity is service:<callerService> plus :<operatorId> when one is sent, so two steps from the same caller service without distinct operatorIds count as self-approval |
NOT_FOUND | 404 | Document or override does not exist, or belongs to another caller |
CONFLICT | 409 | An override request already exists for this document, or the override isn't in the right state for this action (approving/rejecting something not PENDING, witnessing before APPROVED, executing before APPROVED or before a required witness signature). execute also answers Override is no longer approved; it may already have been executed when another execute claimed the override first, and Document has already been deleted when the document was deleted some other way — in that case nothing is changed and the override stays APPROVED |
RATE_LIMITED | 429 | Rate limit exceeded |