Changelog
Changelog
Destacados seleccionados de los últimos lanzamientos. Para ver las versiones completas de la API y la política de cambios disruptivos, consulta el Versionado de API y política LTS.
Cambios detallados en endpoints individuales: Especificación OpenAPI y referencia interactiva de la API.
2026-10 · Colores en el Dashboard
- Nuevo: la página de detalles de un código tiene la tarjeta Colores: primer plano y fondo como valor hexadecimal, fondo transparente y vista previa a través de la ruta de imagen real. La comprobación es la de
PATCH /v1/codes/{id}: los pares críticos necesitan una confirmación y los pares por debajo de 1,5:1 no se pueden guardar. - Restablecer a negro sobre blanco vuelve a entregar en los cuatro formatos los mismos bytes que sin colores. Los códigos sin colores no cambian.
- Los códigos transparentes aparecen sobre un tablero de ajedrez en todas las vistas previas del Dashboard. Detalles: Colores en el Dashboard.
2026-10 · Colores en PDF y EPS
- Nuevo:
qr.pdfyqr.epsdibujanfgybg, como parámetros y como colores guardados. El negro y cualquier gris se escriben como escala de grises (solo placa negra), cualquier otro color como CMYK en porcentajes enteros, por ejemplo1F4E79como C74 M36 Y0 K53. - Fondo como en SVG: Tan pronto como se selecciona un color, se coloca una superficie opaca detrás del código y su zona de silencio, blanca o
bg.bg=transparentno dibuja ninguna. El título permanece negro, la placa del logotipo blanca. - Sin cambios sin colores: Sin
fg/bgy sin colores guardados, ambos formatos entregan los mismos bytes que antes. El PDF de un pasaporte de producto permanece sin color. - Límites: sin perfil ICC, sin PDF/X. Detalles: Colores en la impresión.
2026-09 · Códigos estáticos sin caché de redirección, eliminación simultánea
- Modificado: Los códigos estáticos ya no se encuentran en la caché de redirección. Una llamada a su enlace corto (
redirect_url) siempre lee el estado actual. Por lo tanto, después deDELETE /v1/account, un código estático ya no redirige en la siguiente llamada, mientras que antes lo hacía hasta por 24 horas. Un cambio de plan también tiene efecto inmediato en los códigos estáticos. La eliminación de la cuenta limpia los códigos dinámicos como antes. Los códigos estáticos impresos contienen su destino directamente y no se ven afectados. - Corregido: Dos peticiones
DELETE /v1/codes/:idsimultáneas al mismo código devuelven una vez200y otra vez404. El webhookqr.deletedse envía exactamente una vez, antes dos veces. - Nuevo:
POSTyDELETE /v1/codes/:id/logoresponden con409(errors/conflict) si otra solicitud ha modificado simultáneamente el logotipo del mismo código, y entonces no cambian nada. Antes, un logotipo subido podía permanecer guardado sin usarse. Dos peticionesDELETE /v1/codes/:id/logosimultáneas devuelven ambas200. Detalles: Logotipo.
2026-09 · TypeScript-SDK 1.2.0
- Novedades en
@qr3/sdk1.2.0:client.codes.update()aceptaappearancey devuelve los resultados de la prueba de contraste comoissuesen el resultado; si no hay hallazgos, el campo no se incluye.client.codes.imageUrl()aceptafg,bgyecc. Cada código que devuelve la API (get,list,create,update,batchCreate) incluyetitleyappearance. - Actualizar:
npm install @qr3/sdk@latest. Próximamente en Python, Go y PHP. Detalles: SDKs y CLI y Guardar colores en el código.
2026-09 · La fecha de expiración modificada se aplica en aproximadamente un minuto
- Corregido: Un
PATCHenexpires_atahora limpia la caché de redirección del código. Por lo tanto, la nueva fecha de expiración se aplica en aproximadamente un minuto en lugar de hasta 24 horas después. Anteriormente, una expiración eliminada o pospuesta seguía devolviendo410durante un máximo de 24 horas, y una expiración establecida para el momento actual permitía que la redirección continuara funcionando durante un máximo de 24 horas. - Corregido: Un código creado con
expires_atahora expira a tiempo incluso si la expiración se encuentra dentro de las primeras 24 horas. - Corregido: Si se elimina un código mientras se está subiendo o eliminando su logotipo,
POSTyDELETE /v1/codes/:id/logoresponden con404y no modifican el código eliminado, al igual que ya lo hacePATCH. - Corregido: Un código estático cuyo enlace corto (
redirect_url) haya sido visitado también se almacena en la caché de redirección. Modificarlo, pausarlo o eliminarlo ahora también limpia la caché, no solo en el caso de los códigos dinámicos.
2026-09 · Guardar colores en el código
- Nuevo:
PATCH /v1/codes/:idaceptaappearanceconforeground_colorybackground_color(#RRGGBB, el fondo tambiéntransparent).qr.svgyqr.pngdibujan los colores guardados sin ningún parámetro; un parámetro de consulta como?fg=000000sigue teniendo prioridad. PDF y EPS dibujarán los colores en una versión posterior. - Prueba de contraste: Un par por debajo de 1,5:1 da como resultado
422. Los pares más débiles se guardan y se notifican enmeta.issuescomowarningocritical; un fondo transparente siempre escritical, nunca se bloquea. - Fusión: Los campos omitidos conservan su valor guardado,
nullrestablece. Los cambios simultáneos en el mismo código ya no se sobrescriben entre sí. - En cada respuesta de código:
appearanceestá presente en cada respuesta de código y en los webhooksqr.createdyqr.updated.POST, el lote y la importación lo rechazan con422. - Sin cambios para los códigos existentes: Sin colores guardados, cada código devuelve los mismos bytes que antes. Detalles: Guardar colores en el código.
2026-09 · Colores y corrección de errores como parámetros de las rutas de imagen
- Nuevo: Las cuatro rutas de imagen aceptan
fg(color de primer plano),bg(color de fondo otransparent) yecc(corrección de erroresL,M,Q,H). SVG y PNG dibujan los colores; PDF y EPS los aceptan, pero no los dibujarán hasta una versión posterior.eccse aplica en los cuatro formatos, un logotipo sigue forzandoH. - Transparente:
bg=transparentdevuelve un SVG sin fondo y un PNG con canal alfa real. El fondo debe ser claro y dejar libre la zona de silencio. - Nunca es un error: Los valores no válidos se ignoran; la imagen se entrega exactamente igual que sin parámetros.
- Caché: Cada parámetro efectivo devuelve
Cache-Control: public, max-age=300en lugar de las 24 horas de la imagen estándar. - Sin cambios de comportamiento sin parámetros: Cualquier código existente devuelve los mismos bytes que antes en los cuatro formatos.
- Disponible en todos los planes. Detalles: Colores y corrección de errores.
2026-09 · PDF y EPS ahora también incrustan el logotipo
- Ampliación:
qr.pdfyqr.epsahora incrustan un logotipo configurado de la misma manera queqr.svgyqr.png(ver más abajo), como una imagen incrustada (PDF a través de unImage XObject, EPS a través de un diccionario de imágenes en PostScript, allí solo con%%LanguageLevel: 3), centrado en la misma área, con el mismo aumento de la corrección de errores aH. Anteriormente, ambos formatos no incluían el logotipo; esto ya se ha solucionado. - Caché: Con un logotipo configurado,
qr.pdfyqr.epsahora también devuelvenCache-Control: public, max-age=300en lugar de las 24 horas habituales, exactamente igual que SVG/PNG. - Alternativa: Si la propia imagen del logotipo no se puede procesar (por ejemplo, un objeto guardado dañado), la corrección de errores permanece en
H, pero el área reservada se queda vacía en lugar de mostrar una imagen; nunca se produce un error de servidor. - Sin cambios de comportamiento sin logotipo: Los códigos sin logotipo siguen entregando
qr.pdf/qr.epsde forma idéntica en bytes, con la caché de 24 horas sin cambios. - Detalles e instrucciones de impresión: Logo en el código QR.
2026-09 · Logo en el código QR — Dashboard y API
- Nuevo: Un código ahora puede llevar un logo en el centro. En el Dashboard, la página de detalles de un código crea una tarjeta de logo propia: Seleccionar logo, al añadir por primera vez o al eliminar, confirmar una advertencia con una casilla de verificación obligatoria (ambas acciones cambian el patrón de puntos), luego Subir logo/Eliminar logo. Un Reemplazo no requiere confirmación; solo cambia la imagen, no el patrón. El rol
viewerve el estado y la vista previa, pero ninguna de las tres acciones. - API:
POST /v1/codes/{id}/logo(campo multipartfile; PNG, JPEG o WebP, máximo 1 MB, se rechaza SVG) crea un logo o lo reemplaza;DELETE /v1/codes/{id}/logolo elimina de nuevo y es idempotente. Una imagen demasiado grande devuelve413, un formato no compatible422, el rolviewer403. - Renderizado:
qr.svgyqr.pngincrustan el logo como píxeles reales (512 × 512, normalizado) y para ello elevan la corrección de errores aH. Por lo tanto, añadir y eliminar cambian el patrón de puntos (M↔H), pero un reemplazo no.qr.pdfyqr.epsno incrustan ningún logo y permanecen sin cambios. Un código ya impreso sigue funcionando en cualquier caso, porque el destino codificado no depende del logo; solo tiene que volver a imprimir quien también quiera ver la (nueva) apariencia del logo en el material, y en ese caso no debe mezclar archivos de impresión antiguos y nuevos. - Caché: Con un logo establecido,
qr.svgyqr.pngdevuelvenCache-Control: public, max-age=300en lugar de las 24 horas habituales. Detalles, límites e instrucciones de impresión: Logo en el código QR.
2026-08 · operationId para todas las 75 operaciones, y una guía de cuándo usar para agentes
- Adición: Todas las 75 operaciones de la especificación OpenAPI ahora llevan un
operationId—listCodes,createCode,getCodeStats,archiveWorkspace, etc. Hasta ahora, este campo faltaba por completo, por lo que cada generador tenía que derivar el nombre del método a partir del método HTTP y la ruta (postV1Codes). Dichos nombres dependen de la ruta y cambian con cada reestructuración de la misma. El formato del nombre es el mismo en los 75 lugares:list/get/create/update/replace/delete, o de lo contrario el verbo de la acción de negocio (validateDpp,registerGs1Identifier,pingWebhook). El verbo sigue la lógica de negocio, no el método HTTP —archiveWorkspacees unDELETE,importDppses unPOST. - Impacto en clientes autogenerados: Quienes generen su SDK a partir de la especificación obtendrán métodos renombrados (
postV1Codes→createCode) en la próxima ejecución. Este es el propósito del cambio, pero se trata de un renombrado en código ajeno; por eso se menciona aquí explícitamente. Las rutas, parámetros, formatos de respuesta y códigos de estado no han cambiado; los SDK oficiales, la CLI y el servidor MCP no se ven afectados. - Inicio para agentes:
https://qr3.app/llms.txttiene una sección## When to use qr3.app— seis tareas en lugar de seis funciones, además de la frase que indica para qué qr3.app no es la herramienta adecuada. El servidor MCP ahora proporciona la misma información en el saludo inicial:initializecontrahttps://mcp.qr3.app/mcpresponde con un campoinstructions(antes: once herramientas sin ninguna clasificación). También se incluye qué llamadas necesitan una clave API —initializeytools/listno, pero cadatools/callsí. - Correcciones en
llms.txt: Se contrastaron cuatro datos con producción y no resultaron válidos: (1) el SDK de Pythonqr3appno está publicado en PyPI — la líneapip installse ha eliminado sin reemplazo; (2)Accept: text/markdownse aplica a la página de inicio y al blog, no a todas las páginas renderizadas en el servidor; (3) la dirección de contacto es[email protected], también en el JSON-LD de la página de inicio; (4)/de/security/es una redirección a un ancla, no una página propia. Nuevo enlace:docs.qr3.app/de/skills/. - Aseguramiento: Tres aserciones en
openapi-spec.test.ts— exhaustividad, unicidad,lowerCamelCase—, cada una verificada mediante una mutación. Otras nueve pruebas fijan los cuatro datos corregidos para evitar que vuelvan a ocurrir. - Limitación conocida: Dos de las 75 operaciones están descritas en la especificación, pero responden con
404(GET /v1/codes/{id}/statsyGET /v1/account). Se les ha asignado un nombre aquí y lo perderán de nuevo tan pronto como se decida si se construirán o se eliminarán.
2026-08 · Las reducciones de tarifa y cancelaciones ahora también afectan a los límites
- Corrección: El webhook de Stripe solo escribía el nombre del plan al cambiar de plan o cancelar, no las cuatro columnas de límite de la organización (
max_workspaces,max_members,max_dynamic_codes,max_scans_per_month). Dado que la aplicación de límites toma el máximo entre el valor guardado y la línea de base del plan, una organización con plan reducido o cancelado conservaba sus límites anteriores más altos; la reducción de tarifa no tenía efecto. Ahora, el webhook establece las columnas en la línea de base de la nueva tarifa con cada cambio real de plan, y en la línea de base gratuita en caso de cancelación, tal como ya lo hace la administración de control. - Comportamiento: Las actualizaciones de rutina de la suscripción (renovación, método de pago, prorrateo) siguen sin afectar a los límites; los límites más altos otorgados de forma individual se mantienen sin cambios. Solo un cambio real de plan los restablece a la línea de base de la nueva tarifa.
- Impacto: Sin cambios en la API ni en el formato de respuesta. Las organizaciones cuya reducción de tarifa se realizó antes de esta corrección conservarán los valores antiguos hasta que se aplique el próximo cambio de plan o el soporte los ajuste.
2026-08 · Cursor keyset ahora en todos los endpoints de lista
- Corrección: La corrección del cursor para
GET /v1/codesyGET /v1/dpp(ver más abajo) se ha implementado ahora en todas las demás listas paginadas por cursor:GET /v1/qr-codes/:id/comments,/v1/workspaces,/v1/gs1/identifiers,/v1/members,/v1/audit-logs,/v1/admin/orgs,/v1/admin/usersy/v1/webhooks/:id/deliveries. Todas paginaban únicamente a través decreated_at; las filas con marcas de tiempo idénticas (entradas de auditoría de una operación por lotes, reintentos de webhook, importaciones de miembros) podían perderse en la página siguiente. La clave de ordenación ahora es la tupla(created_at, id)en todas partes. - Cambio en la API: En estas listas,
meta.pagination.next_cursores a partir de ahora también un valor opaco (base64url) en lugar de una marca de tiempo simple; los cursores ilegibles devuelven400, y los antiguos cursores de marca de tiempo se seguirán aceptando de forma transitoria. ExcepciónGET /v1/webhooks/:id/deliveries: allínext_cursorsigue siendo el ID de la última entrega (ID desconocido → primera página). Los clientes que devuelvennext_cursorsin cambios — Dashboard, CLI, SDKs, MCP — no necesitan cambiar nada. - Impacto: No se requiere migración. Si has echado en falta entradas al paginar en alguna de estas listas (por ejemplo, el registro de auditoría o el registro de entregas en el Dashboard): nunca desaparecieron; las listas las muestran por completo a partir de ahora.
2026-08 · Las marcas de tiempo vuelven a ser conformes con OpenAPI tras la edición y eliminación
- Corrección: Tras
PATCH /v1/codes/{id},updated_atse devolvía en formato SQLite sin zona horaria (2026-08-17 09:00:00), aunque la especificación de OpenAPI prometeformat: date-timey la creación (POST) proporciona la marca de tiempo ISO (2026-08-17T09:00:00.000Z). Lo mismo se aplicaba adeleted_at/updated_aten el soft-delete, así como a las rutas de edición y eliminación de claves de API, organizaciones, workspaces, miembros, comentarios y webhooks, además de alast_used_atde claves de API ylast_triggered_atde webhooks. Todas las rutas de escritura registran ahora en formato ISO 8601 (UTC,TyZ). - Impacto: Los clientes que analizan
updated_atconnew Date(...)(SDKs, CLI, Dashboard) leían el formato con espacio como hora local — la CLI mostraba la hora desplazada por el desfase local en los códigos editados una vez (Viena: −2 h). Esto se ha solucionado. Además, una migración de datos normaliza los valores ya almacenados en el formato antiguo a ISO, para que la ordenación y las comparaciones en conjuntos de datos mixtos sean correctas. Sin cambios en los nombres de los campos ni en la estructura de la respuesta. - Contexto: La misma clase de error que las dos correcciones de abajo (expiración de claves de API, límite de reescaneo):
datetime('now')de SQLite escribeYYYY-MM-DD HH:MM:SS, mientras que todos los demás escritores utilizan ISO 8601. Un test de protección en el código fuente evitará que esto vuelva a ocurrir en el futuro.
2026-08 · La paginación de listas ya no pierde códigos batch
- Corrección:
GET /v1/codesyGET /v1/dpppaginaban únicamente a través decreated_at. Sin embargo, los códigos dePOST /v1/codes/batch,POST /v1/dpp/batchy de la importación CSV/XLSX comparten una sola marca de tiempo; tan pronto como un lote era mayor quelimit(por defecto 20), la segunda página ya no entregaba las filas restantes de esa misma marca de tiempo. Los códigos existían y se podía acceder a ellos a través deGET /v1/codes/:id, pero nunca aparecían en la lista (Dashboard, CLIqr3 list, SDKs, MCP). El cursor ahora es un Keyset sobre(created_at, id). - Cambio en la API:
meta.pagination.next_cursores a partir de ahora un valor opaco (base64url) en lugar de una marca de tiempo simple. Quienes devuelvan el cursor sin cambios como?cursor=— tal como lo hacen el Dashboard, la CLI, todos los SDKs y el servidor MCP — no tienen que cambiar nada. Los antiguos cursores de marca de tiempo se seguirán aceptando de forma transitoria; los cursores ilegibles ahora devuelven400en lugar de entregar silenciosamente la primera página. - Impacto: Si después de una importación por lotes veías menos códigos en la lista de los que se habían creado: los códigos nunca desaparecieron; la lista ahora los muestra por completo. No se requiere migración.
2026-08 · Los re-escaneos de seguridad vuelven a ejecutarse cada 24 horas
- Corrección: El re-escaneo periódico de las URLs de destino y los enlaces de la página de destino (Google Web Risk) omitía códigos cuyo último escaneo se encontraba en el mismo día calendario que el límite de 24 horas; dependiendo de la hora, el re-escaneo se retrasaba hasta un día más. El límite ahora se calcula en el mismo formato ISO en el que se almacenan las marcas de tiempo de escaneo.
- Impacto: Una URL de destino que sea clasificada como no segura después del último escaneo volverá a provocar la pausa automática del código dentro de la ventana documentada de 24 horas. Sin cambios en la API ni en el formato de respuesta.
2026-08 · Las claves de API expiran en el momento exacto de su expiración
- Corrección: Una clave de API cuyo
expires_atcoincidía con el mismo día se seguía aceptando hasta la medianoche UTC. Ahora, la expiración se compara como una marca de tiempo en lugar de como una cadena de texto; una clave expirada devuelve inmediatamente401. - Contexto:
expires_atse almacena como una marca de tiempo ISO (2026-08-14T09:00:00Z), mientras que el lado de la comparación proporcionaba el formato con espacio (2026-08-14 09:00:00). Por lo tanto, la comparación directa de cadenas de texto solo funcionaba correctamente si la fecha ya era diferente. - Impacto: No se requiere migración, el formato de respuesta de
GET /v1/api-keyspermanece sin cambios. Los valores de expiración ilegibles ahora se consideran expirados en lugar de válidos.
2026-08 · Referencia de la API: Gestión de inquilinos documentada
- OpenAPI: La especificación — y con ella la referencia interactiva — ahora documenta organizaciones (incl.
GET /v1/organizations/usage), workspaces, miembros y roles y registros de auditoría. - Billing: El resumen de tarifas (
GET /v1/billing/plans) es público; el checkout (POST /v1/billing/checkout) y el portal de clientes de Stripe (GET /v1/billing/portal) están designados como endpoints para administradores de la organización. - Exportación de escaneos: Las estadísticas de escaneo (
GET /v1/codes/{id}/scans) y la exportación de datos brutos (…/scans.csv,…/scans.xlsx) están completamente documentadas — incluyendo el aviso de RGPD: elip_hashnunca está incluido en la exportación. - Comportamiento de errores: También se ha documentado la respuesta
400de la validación de solicitudes: el cuerpo es el error de Zod sin procesar, no un documento de problema RFC-7807 — sin embargo, se entrega bajo el Content-Typeapplication/problem+json.
2026-08 · Copiar enlaces públicos de archivos
- Dashboard: los archivos públicos en la página de detalles de un código ahora tienen un botón que copia su enlace público al portapapeles — listo para usarse como URL de destino de un código QR cuando un escaneo deba abrir de inmediato un documento concreto en lugar de la página de destino con la lista de archivos.
- API: los endpoints de archivos (
/v1/files) ahora devuelven tambiénpublic_url. El campo solo está definido en archivos convisibility: public— los archivos privados no tienen dirección pública. - Comportamiento: el enlace no necesita inicio de sesión y abre el archivo directamente en el navegador. Reemplazar el archivo no modifica el enlace, de modo que un código impreso con él sigue siendo válido. Detalles: Archivos y fichas técnicas.
2026-07 · Roles de equipo: Colaborador sin eliminar y facturación de Administrador
- Nuevo: rol de miembro Colaborador (sin eliminar) — crea y edita códigos QR, archivos y Digital Product Passports, pero no puede eliminar nada ni crear claves de API. Todos los endpoints destructivos comprueban el rol en el servidor (
403). - Facturación: las mejoras de plan y el portal de clientes de Stripe (
POST /v1/billing/checkout,GET /v1/billing/portal) ahora están reservados a los Administradores de la organización — todos los demás roles ven un resumen de plan de solo lectura. - Dashboard: las acciones no permitidas para el rol actual se ocultan: un Lector no ve, por ejemplo, botones para crear, editar o eliminar; las listas, descargas y estadísticas siguen visibles. Detalles: Equipo y roles.
2026-06 · Enlaces externos en la página de destino del código
- Página de destino: La página de destino alojada por qr3 de un código ahora puede listar enlaces externos autoalojados (
{ label, url }) además de o en lugar de los archivos subidos, por ejemplo para fichas técnicas en tu propio sitio. - API:
POST/PATCH /v1/codesaceptan un arraylinks(0–20 entradas,http(s), ≤ 2048 caracteres). Cada URL se verifica con Google Web Risk; una URL no segura devuelve422. Un array vacío elimina todos los enlaces. - Dashboard: Añade, reordena y elimina enlaces en la página de detalles del código.
- Seguridad: Los enlaces renderizados permanecen seguros frente a XSS (escapados, solo
http(s)) y la página mantiene su encabezadonoindex.
2026-04 · Analíticas del Dashboard por código QR
- Dashboard: El botón de analíticas en la lista de códigos QR ahora abre la página de estadísticas del código QR correspondiente en
/dashboard/codes/{id}. - Routing: El alias
/dashboard/codessigue redirigiendo a/dashboard, pero ya no intercepta rutas de detalle como/dashboard/codes/{id}. - API: La página de detalles carga el código QR directamente mediante
GET /v1/codes/:id; de este modo, ya no depende de los límites de paginación de la lista. - Tests: Las pruebas de regresión cubren la redirección del alias y la carga directa del código.
2026-04 · Diálogo de eliminación en el Dashboard para códigos QR
- Dashboard: El icono de papelera en la lista de códigos QR ahora abre un diálogo de React propio en lugar de una ventana emergente nativa del navegador.
- Feedback: Después de la eliminación, aparece una notificación toast de éxito o error.
- Tests:
packages/dashboard/tests/dashboard.test.tsevita regresiones enconfirm()en el flujo de eliminación de códigos QR.
2026-04 · Prueba de enlace corto en el Dashboard para códigos QR dinámicos
- Dashboard: Los shortcodes en la lista de códigos QR ahora se pueden hacer clic directamente como enlaces de redirección externos. El icono de enlace externo junto a, por ejemplo,
wu3qaaabrehttps://qr3.app/{shortCode}en una nueva pestaña. - i18n: Se han añadido textos de información sobre herramientas (tooltips) para alemán e inglés.
- Tests:
packages/dashboard/tests/dashboard.test.tsprotege el href del enlace, el comportamiento de nueva pestaña,noopener noreferrery el icono contra regresiones.
2026-04 · Ruta del Redirect-Worker para códigos QR dinámicos
- Corrección: Los códigos QR dinámicos en
https://qr3.app/{shortCode}vuelven a ser procesados por el Redirect-Worker. La ruta de producción ahora utilizaqr3.app/*porque las rutas de Cloudflare Workers no admiten parámetros de ruta:code. - Robustez: Las rutas que no coinciden se pasan al origen de la landing page para que las páginas normales como
/de/pricingno sean bloqueadas por el Redirect-Worker. - Tests:
packages/redirect/tests/unit/redirect.test.tsverifica la ruta comodín (wildcard), el procesamiento de shortcodes y el paso directo al origen (pass-through).
2026-04 · Resumen de escaneos DPP del Workspace (Q3.4.2)
- Nuevo:
GET /v1/workspace/stats/dpp?days=30— agrega todos losdpp_scansdel Workspace de la clave API (active_dpps,scans_by_day,top_dppscon nombre de producto/categoría). - Dashboard: Tarjeta en la página de inicio (
/dashboard) con gráfico de barras de 30 días + listas principales — en paralelo a las tarjetas de códigos QR. - Public: Enlace corto de marketing
GET /dpp/dpp_<id>(un segmento) para demostraciones en vivo, en paralelo a/dpp/{gtin}/{serial}.
2026-04 · Analíticas de escaneos DPP (Q3.4.1)
- Nuevo:
GET /v1/dpp/:id/stats?days=30— escaneos agregados del resolver público GS1 por DPP. Campos:total_scans,period_scans,scans_by_day,top_countries,top_devices,top_representations. - Nuevo: Tabla
dpp_scans(migración0011) — separada descans(Redirect-Worker). Las direcciones IP se cifran con un hash utilizando una sal (salt) rotativa diaria, las IP en bruto nunca llegan a D1. - Dashboard: Tarjeta de minigráfico (SVG, sin biblioteca de gráficos) en
/dashboard/dpp/:dppIdcon barras de 30 días + desgloses de los 3 principales. Estado vacío (empty state) tan pronto como un DPP esté activo pero aún no haya tenido escaneos.
2026-04 · Simulador de conformidad de la UE en vivo (Q3.3.7)
- Nuevo:
POST /v1/dpp/:id/validate-update— simula actualizaciones parciales sin estado (stateless) (estado, lista de mercados, …) sin persistencia. La respuesta contieneeu_compliance+preview.changed_fields. - Dashboard: Tarjeta de simulador en el detalle del DPP (
/dashboard/dpp/:dppId) — etiquetas (chips) paraDE/AT/FR/IT/ES/NL+ personalizadas, menú desplegable de estado, Preview EU impact / Save changes / Reset. No bloqueante a través de RemixuseFetcher. - Robustez: Funciones auxiliares del simulador externalizadas (
readUpdatePatchFromForm,marketCountriesKey) + 18 nuevas pruebas unitarias; corrección de errores: la entrada única no ISO ya no borra la lista de mercados.
2026-04 · Vista previa de conformidad de la UE en vivo en el formulario de creación (Q3.3.6)
- Modificado:
POST /v1/dpp/validateahora también devuelveeu_compliance— el mismo validador queGET /v1/dpp/:id/eu-compliance, sin estado (stateless) antes de guardar. - Dashboard: Vista previa debajo del panel de validación existente + nuevo banner de protección de guardado antes de los botones de envío si hay errores/advertencias pendientes (pluralización i18n DE/EN).
2026-04 · Validador de la UE + UI textil (Q3.3.4 + Q3.3.5)
- Nuevo: Validador de conformidad de la UE con 5 reglas textiles (
TEXTILE_AGEC_REQUIRED,TEXTILE_MICROPLASTICS_CONSISTENCY,TEXTILE_SVHC_THRESHOLD,TEXTILE_GREENWASHING,TEXTILE_ESPR_READY). - Nuevo:
GET /v1/dpp/:id/eu-complianceconcompliant/espr_ready/issues[]/summary. - Dashboard: Sección de conformidad de la UE en el detalle del DPP (mosaicos de resumen, tarjetas de problemas agrupadas, insignia ESPR-Ready en el encabezado).
2026-04 · Esquema DPP textil (Q3.3.1–Q3.3.3)
- Nuevo: Categoría
textilecon cadena obligatoria AGEC (tejeduría/punto → teñido/estampado → confección), por fibraorigin_country+recycled_pct,svhc_substances[], opción de exclusión voluntaria (opt-in) de ESPR (PEF, vida útil, reciclabilidad). - Nuevo: Campo básico
market_countries: string[](ISO 3166-1 alpha-2) en todas las categorías DPP — controla las reglas AGEC específicas de Francia y la nota obligatoria para el consumidor francés. - Nuevo: Plantilla HTML para el consumidor con cuadro de advertencia de microplásticos AGEC, cadena de origen de 3 niveles (píldoras con banderas), lista SVHC, sección de durabilidad y reciclabilidad.
- Migración:
0010_dpp_market_countries(D1).
2026-04 · Importación masiva de DPP (Q3.2.1–Q3.2.5)
- Nuevo:
POST /v1/dpp/importacepta CSV y XLSX (compatible con Workers a través de SheetJSxlsx, ~283 KB de paquete comprimido con gzip). - Escalado: límite basado en el plan (Free 100 → Enterprise 10k) +
db.batch()fragmentado (chunked) de 100 en 100 + límite de cuerpo de 5 MB. - Nuevo: Informe de errores en formato CSV en el campo
errors_csvde la respuesta 201;GET /v1/dpp/import/templates/:category?format=csv|xlsxproporciona plantillas listas para usar para baterías y textiles. - Dashboard: Carga mediante arrastrar y soltar (drag-and-drop) en
/dashboard/dpp/importcon proxy de plantilla y descarga de CSV en línea.
Sin cambios disruptivos — Extensiones LTS
Todos los cambios mencionados anteriormente son aditivos:
- Los clientes existentes de
POST /v1/dpp/validateignoran el nuevo campoeu_compliancesin necesidad de realizar cambios. - Los flujos de
batteryexistentes permanecen sin cambios. market_countrieses opcional y tiene como valor predeterminado[].
Consulta Versionado de API para conocer la política de cambios disruptivos.