Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nayalsaurav/Storx/llms.txt

Use this file to discover all available pages before exploring further.

Storx uses a two-stage deletion model. Moving a file to trash is a reversible soft-delete that hides the file from your main view but leaves it intact in ImageKit CDN. Permanent deletion removes both the database record and the CDN asset in one irreversible operation.

How Trash Works

Trash state is stored as the isTrash boolean column on the files table:
// lib/db/schema.ts
export const files = pgTable("files", {
  // ...
  isTrash: boolean("is_trash").default(false).notNull(),
  // ...
});
When a file is moved to trash, only the database flag is changed — the file remains in ImageKit CDN at its original URL and continues to count against your storage quota. No CDN operation is performed at this stage. The trash pattern keeps accidental deletions recoverable without requiring a separate backup mechanism.

Moving Files to Trash

The PATCH /api/files/[fileId]/trash endpoint toggles isTrash on the target file, mirroring the same server-side toggle pattern used by the star endpoint:
// app/api/files/[fileId]/trash/route.ts
const [file] = await db
  .select()
  .from(files)
  .where(and(eq(files.id, fileId), eq(files.userId, userId)));

const updatedFiles = await db
  .update(files)
  .set({ isTrash: !file.isTrash })   // server-side toggle
  .where(and(eq(files.id, fileId), eq(files.userId, userId)))
  .returning();

return NextResponse.json(updatedFiles[0], { status: 200 });
PATCH /api/files/{fileId}/trash Request body:
{
  "userId": "user_2abc123"
}
Successful response (200 OK) — the full updated database record:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "old-invoice.pdf",
  "size": 102400,
  "type": "application/pdf",
  "fileUrl": "https://ik.imagekit.io/.../old-invoice.pdf",
  "thumbnailUrl": null,
  "imagekitFileId": "ik_xyz789",
  "userId": "user_2abc123",
  "parentId": null,
  "isFolder": false,
  "isStarred": false,
  "isTrash": true,
  "createdAt": "2024-01-10T09:00:00.000Z",
  "updatedAt": "2024-01-15T14:00:00.000Z"
}

Permanently Deleting Files

Permanently deleting a file requires the DELETE /api/files/{fileId} endpoint. This endpoint:
1

Authenticate the request

Verifies the Clerk session and confirms that the userId in the request body matches the authenticated user.
2

Look up the file

Queries the files table to confirm the record exists and belongs to the authenticated user.
3

Delete from ImageKit CDN

Calls imagekit.deleteFile(fileId) to permanently remove the binary asset from the CDN.
4

Delete the database record

Removes the row from the files table via Drizzle ORM and returns the deleted record.
// app/api/files/[fileId]/delete/route.ts
// Delete the file from ImageKit
await imagekit.deleteFile(fileId);

// Delete the database record
const deletedFiles = await db
  .delete(files)
  .where(and(eq(files.id, fileId), eq(files.userId, userId)))
  .returning();
DELETE /api/files/{fileId} Request body:
{
  "userId": "user_2abc123"
}
Successful response (200 OK):
{
  "message": "File deleted successfully",
  "deletedFile": { "...full FileItem record..." }
}
The app/api/files/[fileId]/empty-trash/route.ts file exists in the codebase but contains no implementation. Bulk-emptying the trash is not yet supported.
Calling DELETE /api/files/{fileId} permanently removes the file from ImageKit CDN via imagekit.deleteFile(). This operation cannot be undone — the CDN asset is gone immediately and there is no recovery path. Always move files to trash first and confirm you no longer need them before performing a permanent delete.

Restoring Files

Because PATCH /api/files/[fileId]/trash toggles isTrash, sending the same request a second time when isTrash = true sets it back to false, effectively restoring the file to your main view:
// First call  → isTrash: false → true  (moves to trash)
// Second call → isTrash: true  → false (restores from trash)
PATCH /api/files/550e8400-e29b-41d4-a716-446655440000/trash
{ "userId": "user_2abc123" }
After restoring, the file reappears in the folder it was originally located in and is accessible at its original ImageKit URL — nothing was changed in CDN during either the trash or restore operation. Error responses for all trash-related endpoints:
StatusBodyCause
401{ "error": "Unauthorized" }Missing session or userId mismatch
400{ "error": "File id is required" }fileId path param is empty
404{ "error": "File not found" }No matching file for this user
500{ "error": "Failed to mark file as trash" }Database error

Build docs developers (and LLMs) love