bulk_update_qr_codes
Update multiple QR codes simultaneously by modifying target URLs, labels, expiration dates, or scheduled changes in a single batch operation.
Instructions
Update multiple QR codes in a single request (up to 50). Change target URLs and/or labels. Items with non-existent short_id are reported as not_found without failing the whole batch.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| items | Yes | Array of QR code updates. Max 50 per request. |
Implementation Reference
- src/modules/qr/qr.service.ts:446-506 (handler)Implementation of the bulk_update_qr_codes logic.
export function bulkUpdateQrCodes( items: Array<{ short_id: string; target_url?: string; label?: string; [key: string]: unknown }>, apiKeyId: number ) { let updated = 0; let notFound = 0; const results: Array<{ short_id: string; status: "updated" | "not_found"; target_url?: string; label?: string }> = []; for (const item of items) { const existing = db .select() .from(qrCodes) .where(and(eq(qrCodes.shortId, item.short_id), eq(qrCodes.apiKeyId, apiKeyId))) .get(); if (!existing) { notFound++; results.push({ short_id: item.short_id, status: "not_found" }); continue; } const type = (existing.type as QrType) || "url"; const updateSet: Record<string, unknown> = { updatedAt: new Date().toISOString(), }; if (item.label !== undefined) updateSet.label = item.label; if (type === "url") { if (item.target_url !== undefined) updateSet.targetUrl = item.target_url; if (item.expires_at !== undefined) updateSet.expiresAt = item.expires_at; if (item.scheduled_url !== undefined) updateSet.scheduledUrl = item.scheduled_url; if (item.scheduled_at !== undefined) updateSet.scheduledAt = item.scheduled_at; if (item.utm_params !== undefined) updateSet.utmParams = item.utm_params ? JSON.stringify(item.utm_params) : null; if (item.gtm_container_id !== undefined) updateSet.gtmContainerId = item.gtm_container_id; if (item.redirect_rules !== undefined) updateSet.redirectRules = item.redirect_rules ? JSON.stringify(item.redirect_rules) : null; } // Type-specific data: merge partial updates const typeDataKey = `${type}_data`; const itemData = item[typeDataKey]; if (type !== "url" && itemData && typeof itemData === "object") { const current = existing.typeData ? JSON.parse(existing.typeData) : {}; updateSet.typeData = JSON.stringify({ ...current, ...itemData as object }); } db.update(qrCodes) .set(updateSet) .where(eq(qrCodes.shortId, item.short_id)) .run(); updated++; results.push({ short_id: item.short_id, status: "updated", ...(item.target_url !== undefined && { target_url: item.target_url }), ...(item.label !== undefined && { label: item.label }), }); } return { updated, not_found: notFound, items: results }; } - packages/mcp/src/tools.ts:237-259 (registration)Registration of the bulk_update_qr_codes MCP tool.
bulk_update_qr_codes: { description: "Update multiple QR codes in a single request (up to 50). Change target URLs and/or labels. Items with non-existent short_id are reported as not_found without failing the whole batch.", inputSchema: z.object({ items: z .array( z.object({ short_id: z.string().describe("The short_id of the QR code to update."), target_url: z.string().url().optional().describe("New destination URL."), label: z.string().optional().describe("New label."), expires_at: z.string().nullable().optional().describe("ISO 8601 expiration date. Null to clear."), scheduled_url: z.string().url().nullable().optional().describe("Replacement URL. Null to cancel."), scheduled_at: z.string().nullable().optional().describe("ISO 8601 activation date. Null to cancel."), }) ) .min(1) .max(50) .describe("Array of QR code updates. Max 50 per request."), }), handler: async (input: Record<string, unknown>) => { return apiRequest("/api/qr/bulk", { method: "PATCH", body: input }); }, },