Skip to content

API Reference — Permanent deletion

Permanent deletion hard-deletes your data: it erases the file bytes from storage, removes the database record, and gives the storage back to your quota. There is no undo and no "undelete" endpoint. Use these endpoints only when you intend the data to be gone for good.

If you only want a recoverable delete (move to Trash), use the soft-delete on the Files endpoint instead — that leaves the bytes in place and restorable. The endpoints on this page are the irreversible counterpart.

Method & pathWhat it doesScope
DELETE /gdpr/files/{file_id}Permanently erase one file and free its quotafiles:write
DELETE /gdpr/trashPermanently empty Trash (runs in the background)files:write
  • Base URL: https://api-cloud.fluidvip.com/api/v1
  • Auth: send your key in X-API-Key (or Authorization: Bearer). See Authentication.
  • Both endpoints require the files:write scope. A request without it returns 403 with a structured detail whose error is insufficient_scope. See Errors.

Irreversible. Once a permanent-deletion call commits, the bytes are removed from object storage and the row is removed from the database. There is no recovery path at the application layer. Walk through the consequences before you call these endpoints — and read Deleting data for the soft-delete vs. hard-delete decision.


Delete one file permanently

DELETE /gdpr/files/{file_id}

Hard-deletes a single file your tenant owns. This is allowed whether or not the file is currently in Trash — you do not need to soft-delete it first. In one atomic operation the API:

  1. Revokes and deletes every share link pointing at the file (the link is killed at the edge first, then the record is removed).
  2. Erases the file's bytes from object storage.
  3. Releases the file's bytes back to your storage quota.
  4. Deletes the file record.

After this returns, any raw link (https://files.fluidadmin.com/s/<token>) that pointed at this file is dead and the file id no longer resolves.

Edge-cache caveat. A revoked permanent link can still serve from edge cache until its max-age of 3600 seconds (1 hour) lapses. Treat permanent deletion as taking effect immediately for the API and within up to an hour at the edge.

Path parameters

NameTypeDescription
file_idUUID stringThe id of the file to erase.

Response

204 No Content — success, empty body.

Status codes

StatusMeaning
204File permanently deleted.
401Missing, invalid, or revoked API key.
403insufficient_scope — the key lacks files:write.
404File not found, or it is not yours. (Cross-tenant ids return 404, never 403, so existence never leaks.)
429Rate limited — retry after the Retry-After header.

There is no 409 quarantine check here: unlike sharing or serving, you may permanently delete a file at any time, including while it is still being scanned.

Examples

curl

bash
curl -X DELETE "https://api-cloud.fluidvip.com/api/v1/gdpr/files/3f1c8e2a-7b4d-4a9e-9c1f-2d6b0a4e8f10" \
  -H "X-API-Key: fck_live_your_key_here" \
  -i

A successful call returns HTTP/1.1 204 No Content with no body.

Python (pip install fluidcloud)

python
from fluidcloud import FluidCloud, NotFoundError

fc = FluidCloud(api_key="fck_live_your_key_here")

try:
    fc.files.delete_permanent("3f1c8e2a-7b4d-4a9e-9c1f-2d6b0a4e8f10")
    print("Erased.")
except NotFoundError:
    print("Already gone (or not yours).")

TypeScript (npm install fluidcloud)

ts
import { FluidCloud, NotFoundError } from "fluidcloud";

const fc = new FluidCloud({ apiKey: "fck_live_your_key_here" });

try {
  await fc.files.deletePermanent("3f1c8e2a-7b4d-4a9e-9c1f-2d6b0a4e8f10");
  console.log("Erased.");
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log("Already gone (or not yours).");
  } else {
    throw err;
  }
}

Idempotency tip. A second permanent-delete on the same id returns 404, not an error you need to special-case — the file is simply already gone. If you delete by your own logical key, resolve it first (see Files → resolve by client_key); a resolve that 404s means the file no longer exists.


Empty Trash permanently

DELETE /gdpr/trash

Permanently purges everything currently in Trash for your tenant — every soft-deleted file (bytes, record, and its share links) and every soft-deleted folder. This is the bulk counterpart to deleting one file.

Because a Trash can hold thousands of files, the purge runs in the background. The call returns immediately with a count of what is being purged; the actual erasure completes asynchronously. Calling it again for the same scope while a sweep is already in progress is a no-op.

Irreversible, and broad. Without space_id, this empties the Trash across every space in your tenant in one shot. Make sure that is what you want — restore anything you might still need (via the Files endpoint) before you call this.

Query parameters

NameTypeRequiredDescription
space_idUUID stringNoLimit the purge to one space's Trash. Omit it to empty the universal Trash across every space in the tenant.

Response

200 OK with a JSON body:

json
{
  "status": "emptying",
  "files": 142,
  "bytes": 7340032
}
FieldTypeDescription
statusstringAlways "emptying" — the background sweep has been accepted.
filesintegerNumber of trashed files counted for this purge at request time.
bytesintegerTotal bytes those files occupy. This is roughly the quota you will get back when the sweep finishes.

Because the sweep is asynchronous, a 200 means the purge was accepted and started, not that it has finished. Quota is released as files are erased; re-read it via the Quota endpoint shortly after to see the freed space.

Status codes

StatusMeaning
200Purge accepted and started (or a no-op if one was already running for this scope).
401Missing, invalid, or revoked API key.
403insufficient_scope — the key lacks files:write.
404space_id was supplied but no such space exists in your tenant.
429Rate limited — retry after the Retry-After header.

Examples

curl — empty the entire tenant's Trash:

bash
curl -X DELETE "https://api-cloud.fluidvip.com/api/v1/gdpr/trash" \
  -H "X-API-Key: fck_live_your_key_here"

curl — empty only one space's Trash:

bash
curl -X DELETE "https://api-cloud.fluidvip.com/api/v1/gdpr/trash?space_id=9a2b7c1d-4e5f-4a6b-8c9d-0e1f2a3b4c5d" \
  -H "X-API-Key: fck_live_your_key_here"

Python

python
from fluidcloud import FluidCloud

fc = FluidCloud(api_key="fck_live_your_key_here")

# Empty the whole tenant's Trash.
result = fc.trash.empty()
print(result["status"], result["files"], "files")

# Or scope to a single space.
fc.trash.empty(space_id="9a2b7c1d-4e5f-4a6b-8c9d-0e1f2a3b4c5d")

TypeScript

ts
import { FluidCloud } from "fluidcloud";

const fc = new FluidCloud({ apiKey: "fck_live_your_key_here" });

// Empty the whole tenant's Trash.
const result = await fc.trash.empty();
console.log(result.status, result.files, "files");

// Or scope to a single space.
await fc.trash.empty({ spaceId: "9a2b7c1d-4e5f-4a6b-8c9d-0e1f2a3b4c5d" });

Partial-on-interruption is safe. The sweep purges in batches. If it is interrupted, the files already purged are gone and the rest stay in Trash, ready to be purged by a later call. You can safely re-issue DELETE /gdpr/trash for the same scope.


What you cannot do with an API key

Tenant-wide erase (deleting your entire account and all of its data) and per-app erase are not available to API keys. Those operations are owner-only actions performed from the FluidCloud dashboard. An API key is scoped to file-level and Trash-level permanent deletion only.


  • Deleting data — the soft-delete (Trash) vs. permanent-delete workflow, and when to use each.
  • Files — soft-delete to Trash, restore, and resolve by client_key.
  • Shares — share links and how revocation behaves at the edge.
  • Quota — read your storage usage; permanent deletion frees it.
  • Errors — full error model and typed SDK errors.
  • Rate limits — per-key and per-action limits.

FluidCloud API — part of the Fluidvip ecosystem.