Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ephraimduncan/minimal.so/llms.txt
Use this file to discover all available pages before exploring further.
The bookmark API provides two bulk operations for efficiently managing multiple bookmarks at once.
Bulk Delete
Delete multiple bookmarks in a single operation.
Endpoint
client.bookmark.bulkDelete(input)
Defined in: server/procedures/bookmarks.ts:207
Authentication
This endpoint requires authentication. See Authentication for details.
Request
Array of bookmark IDs to delete. Must contain at least one ID.
Input Schema
{
ids: string[]; // min: 1
}
Defined in lib/schema.ts:126.
Response
Always true when the operation completes
Number of bookmarks actually deleted
Examples
Delete Selected Bookmarks
import { orpc } from '@/lib/orpc';
function BulkDeleteButton({ selectedIds }: { selectedIds: string[] }) {
const bulkDeleteMutation = orpc.bookmark.bulkDelete.useMutation();
const handleBulkDelete = async () => {
const result = await bulkDeleteMutation.mutateAsync({
ids: selectedIds,
});
console.log(`Deleted ${result.count} bookmarks`);
};
return (
<button
onClick={handleBulkDelete}
disabled={selectedIds.length === 0 || bulkDeleteMutation.isPending}
>
Delete {selectedIds.length} bookmarks
</button>
);
}
Delete with Confirmation
import { client } from '@/lib/orpc';
async function deleteMultipleBookmarks(bookmarkIds: string[]) {
if (bookmarkIds.length === 0) {
throw new Error('No bookmarks selected');
}
const confirmed = confirm(
`Delete ${bookmarkIds.length} bookmarks? This cannot be undone.`
);
if (!confirmed) return null;
const result = await client.bookmark.bulkDelete({
ids: bookmarkIds,
});
return result;
}
Implementation
From server/procedures/bookmarks.ts:207:
export const bulkDeleteBookmarks = authed
.input(bulkDeleteBookmarksSchema)
.handler(async ({ context, input }) => {
const result = await db.bookmark.deleteMany({
where: { id: { in: input.ids }, userId: context.user.id },
});
return { success: true, count: result.count };
});
Bulk Move
Move multiple bookmarks to a different group in a single operation.
Endpoint
client.bookmark.bulkMove(input)
Defined in: server/procedures/bookmarks.ts:216
Authentication
This endpoint requires authentication. See Authentication for details.
Request
Array of bookmark IDs to move. Must contain at least one ID.
ID of the destination group. The group must exist and belong to the authenticated user.
Input Schema
{
ids: string[]; // min: 1
targetGroupId: string;
}
Defined in lib/schema.ts:130.
Response
Always true when the operation completes
Number of bookmarks actually moved
Examples
Move Selected Bookmarks
import { orpc } from '@/lib/orpc';
function MoveBookmarksButton({
selectedIds,
targetGroupId
}: {
selectedIds: string[];
targetGroupId: string;
}) {
const bulkMoveMutation = orpc.bookmark.bulkMove.useMutation();
const handleMove = async () => {
const result = await bulkMoveMutation.mutateAsync({
ids: selectedIds,
targetGroupId,
});
console.log(`Moved ${result.count} bookmarks`);
};
return (
<button onClick={handleMove}>
Move to group
</button>
);
}
Move with Group Selection
import { client } from '@/lib/orpc';
async function moveBookmarksToGroup(
bookmarkIds: string[],
targetGroupId: string
) {
const result = await client.bookmark.bulkMove({
ids: bookmarkIds,
targetGroupId,
});
return {
movedCount: result.count,
allMoved: result.count === bookmarkIds.length,
};
}
Organize Bookmarks
import { serverClient } from '@/lib/orpc.server';
async function organizeBookmarks(
bookmarkIds: string[],
newGroupId: string
) {
// Move bookmarks to new group
const result = await serverClient.bookmark.bulkMove({
ids: bookmarkIds,
targetGroupId: newGroupId,
});
// Note: isPublic is automatically reset to null
console.log(`Organized ${result.count} bookmarks`);
return result;
}
Implementation
From server/procedures/bookmarks.ts:216:
export const bulkMoveBookmarks = authed
.input(bulkMoveBookmarksSchema)
.handler(async ({ context, input }) => {
await assertGroupOwnership(input.targetGroupId, context.user.id);
const result = await db.bookmark.updateMany({
where: { id: { in: input.ids }, userId: context.user.id },
data: {
groupId: input.targetGroupId,
isPublic: null,
updatedAt: new Date(),
},
});
return { success: true, count: result.count };
});
Behavior
Group Ownership Verification
The target group must exist and belong to the authenticated user:
await assertGroupOwnership(input.targetGroupId, context.user.id);
If the group is invalid, a NOT_FOUND error is thrown.
Visibility Reset
When bookmarks are moved to a different group, their isPublic status is automatically reset to null:
data: {
groupId: input.targetGroupId,
isPublic: null, // Reset visibility
updatedAt: new Date(),
}
This prevents public/private settings from carrying over between groups.
Timestamp Update
The updatedAt timestamp is automatically updated for all moved bookmarks.
Common Behaviors
User Scoping
Both operations automatically filter to only affect the authenticated user’s bookmarks:
where: { id: { in: input.ids }, userId: context.user.id }
Bookmarks belonging to other users are silently ignored, even if their IDs are included.
Partial Success
The count field in the response indicates how many bookmarks were actually affected:
if (result.count < bookmarkIds.length) {
console.log(`Only ${result.count} of ${bookmarkIds.length} bookmarks were processed`);
}
This can happen if:
- Some IDs don’t exist
- Some IDs belong to other users
- Some bookmarks were already deleted
Validation
Both operations require at least one ID:
ids: z.array(z.string()).min(1)
Passing an empty array will result in a validation error.
Errors
For bulk move: The target group doesn’t exist or doesn’t belong to the authenticated user.
User is not authenticated.
The ids array is empty or contains invalid data.
Performance Considerations
- Both operations use
updateMany/deleteMany for efficient batch processing
- More performant than calling individual delete/update endpoints in a loop
- Recommended for operations affecting more than 3-5 bookmarks
- No strict limit on the number of IDs, but consider chunking very large operations (1000+)
Related Endpoints