Changelog
Changelog
Kurerade höjdpunkter från de senaste versionerna. För fullständiga API-versioner och policy för brytande ändringar, se API-versionering & LTS-policy.
Detaljerade ändringar för enskilda slutpunkter: OpenAPI-specifikation och interaktiv API-referens.
2026-08 · Keyset-cursor nu på alla list-slutpunkter
- Fix: Cursor-fixen för
GET /v1/codesochGET /v1/dpp(se nedan) har nu rullats ut till alla övriga cursor-paginerade listor:GET /v1/qr-codes/:id/comments,/v1/workspaces,/v1/gs1/identifiers,/v1/members,/v1/audit-logs,/v1/admin/orgs,/v1/admin/usersoch/v1/webhooks/:id/deliveries. Alla bläddrade tidigare enbart viacreated_at; rader med identisk tidsstämpel (audit-loggposter från en batch-operation, webhook-retries, medlemsimporter) kunde gå förlorade på nästa sida. Sorteringsnyckeln är nu överallt tupeln(created_at, id). - API-ändring: I dessa listor är
meta.pagination.next_cursorfrån och med nu också ett opakt värde (base64url) istället för en ren tidsstämpel; oläsbara cursors returnerar400, gamla tidsstämpel-cursors accepteras fortfarande under en övergångsperiod. UndantagGET /v1/webhooks/:id/deliveries: där förblirnext_cursorID:t för den senaste leveransen (okänt ID → första sidan). Klienter som returnerarnext_cursoroförändrat — Dashboard, CLI, SDKs, MCP — behöver inte ändra någonting. - Konsekvens: Ingen migrering krävs. Om du har saknat poster när du bläddrat i någon av dessa listor (t.ex. audit-loggen eller leveransloggen i Dashboard): De var aldrig borta — listorna visar dem fullständigt från och med nu.
2026-08 · Tidsstämplar efter redigering och radering åter OpenAPI-kompatibla
- Fix: Efter
PATCH /v1/codes/{id}returneradesupdated_ati SQLite-format utan tidszon (2026-08-17 09:00:00), trots att OpenAPI-specifikationen utlovarformat: date-timeoch skapande (POST) returnerar ISO-tidsstämpeln (2026-08-17T09:00:00.000Z). Detsamma gällde fördeleted_at/updated_atvid soft-delete samt för redigerings-/raderingssökvägarna för API-nycklar, organisationer, workspaces, medlemmar, kommentarer och webhooks, och dessutom förlast_used_atför API-nycklar ochlast_triggered_atför webhooks. Alla skrivsökvägar stämplar nu ISO 8601 (UTC,TochZ). - Konsekvens: Klienter som parsar
updated_atmednew Date(...)(SDKs, CLI, Dashboard) läste formatet med mellanslag som lokal tid — CLI visade tiden för koder som redigerats en gång förskjuten med den lokala tidsförskjutningen (Wien: −2 h). Detta är åtgärdat. Dessutom normaliserar en datamigrering redan sparade värden i det gamla formatet till ISO, så att sortering och jämförelser i blandade data blir korrekta. Inga ändringar av fältnamn eller svarsstruktur. - Bakgrund: Samma felklass som de två korrigeringarna nedan (utgångstid för API-nycklar, re-scan-cutoff): SQLites
datetime('now')skriverYYYY-MM-DD HH:MM:SS, alla andra skrivare ISO 8601. Ett källkodstest (guard test) förhindrar framtida förekomster.
2026-08 · Listpaginering tappar inte längre batchkoder
- Fix:
GET /v1/codesochGET /v1/dpppaginerade enbart viacreated_at. Koder frånPOST /v1/codes/batch,POST /v1/dpp/batchoch CSV/XLSX-importen delar dock på en tidsstämpel — så fort en batch var större änlimit(standardvärde 20), returnerade den andra sidan inte längre de återstående raderna för samma tidsstämpel. Koderna existerade och var tillgängliga viaGET /v1/codes/:id, men dök aldrig upp i listan (Dashboard, CLIqr3 list, SDKs, MCP). Cursorn är nu ett keyset över(created_at, id). - API-ändring:
meta.pagination.next_cursorär från och med nu ett opakt värde (base64url) istället för en ren tidsstämpel. De som returnerar cursorn oförändrad som?cursor=— precis som Dashboard, CLI, alla SDKs och MCP-servern gör — behöver inte ändra någonting. Gamla tidsstämpel-cursors accepteras fortfarande under en övergångsperiod; oläsbara cursors returnerar nu400istället för att tyst leverera den första sidan. - Konsekvens: För de som såg färre koder i listan efter en batchimport än vad som skapades: Koderna var aldrig borta — listan visar dem fullständigt från och med nu. Ingen migrering krävs.
2026-08 · Säkerhets-re-scans körs återigen i 24-timmarstakt
- Fix: Den periodiska re-scanningen av mål-URL:er och länkar på landningssidor (Google Web Risk) hoppade över koder vars senaste skanning inföll på samma kalenderdag som 24-timmars-cutoffen — beroende på klockslag fördröjdes re-scannen med upp till ytterligare en dag. Cutoffen beräknas nu i samma ISO-format som skanningstidsstämplarna är sparade i.
- Konsekvens: En mål-URL som klassificeras som osäker efter den senaste skanningen leder återigen till att koden pausas automatiskt inom det dokumenterade 24-timmarsfönstret. Inga ändringar i API eller svarsformat.
2026-08 · API-nycklar löper ut vid utgångstidpunkten
- Fix: En API-nyckel vars
expires_atinföll samma dag fortsatte att accepteras fram till midnatt UTC. Utgångstiden jämförs nu som en tidsstämpel istället för som en sträng — en utgången nyckel returnerar omedelbart401. - Bakgrund:
expires_atsparas som en ISO-tidsstämpel (2026-08-14T09:00:00Z), medan jämförelsesidan returnerade formatet med mellanslag (2026-08-14 09:00:00). Den råa strängjämförelsen stämde därför endast så länge som själva datumet skilde sig åt. - Konsekvens: Ingen migrering krävs, svarsformatet för
GET /v1/api-keysförblir oförändrat. Oläsbara utgångsvärden betraktas nu som utgångna istället för giltiga.
2026-08 · API-referens: Tenant-hantering dokumenterad
- OpenAPI: Specifikationen — och därmed den interaktiva referensen — dokumenterar nu organisationer (inkl.
GET /v1/organizations/usage), workspaces, medlemmar & roller och audit-loggar. - Billing: Abonnemangsöversikten (
GET /v1/billing/plans) är offentlig; checkout (POST /v1/billing/checkout) och Stripe-kundportalen (GET /v1/billing/portal) är angivna som slutpunkter för organisationsadministratörer. - Skanningsexport: Skanningsstatistik (
GET /v1/codes/{id}/scans) och rådataexporten (…/scans.csv,…/scans.xlsx) är fullständigt dokumenterade — inklusive GDPR-information:ip_hashär aldrig inkluderad i exporten. - Felbeteende: Även
400-svaret från request-valideringen är nu dokumenterat: Bodyn är det råa Zod-felet, inte ett RFC-7807-problemdokument — det levereras ändå med Content-Typeapplication/problem+json.
2026-08 · Kopiera offentliga fillänkar
- Dashboard: Offentliga filer på koddetaljsidan har nu en knapp som kopierar deras offentliga länk till urklipp – direkt användbar som måladress för en QR-kod om en skanning omedelbart ska öppna ett specifikt dokument istället för landningssidan med fillistan.
- API: Fil-slutpunkterna (
/v1/files) returnerar nu ävenpublic_url. Fältet är endast satt för filer medvisibility: public– privata filer får ingen offentlig adress. - Beteende: Länken kräver ingen inloggning och öppnar filen direkt i webbläsaren. Att ersätta filen lämnar länken oförändrad, så en tryckt kod förblir giltig. Detaljer: Filer & datablad.
2026-07 · Teamroller: Redaktör utan borttagning & administratörsfakturering
- Nytt: Medlemsrollen Redaktör (utan borttagning) — skapar och redigerar QR-koder, filer och Digital Product Passports, men kan inte ta bort något eller skapa API-nycklar. Alla destruktiva slutpunkter kontrollerar rollen på serversidan (
403). - Fakturering: Abonnemangsuppgraderingar och Stripe-kundportalen (
POST /v1/billing/checkout,GET /v1/billing/portal) är nu reserverade för organisationsadministratörer — alla andra roller ser en skrivskyddad abonnemangsöversikt. - Dashboard: Åtgärder som den egna rollen inte tillåter döljs: En Läsare ser till exempel inga knappar för att skapa, redigera eller ta bort; listor, nedladdningar och statistik förblir synliga. Detaljer: Team & roller.
2026-06 · Externa länkar på kodens landningssida
- Landningssida: Landningssidan för en kod som är värd på qr3 kan nu lista externa, självhostade länkar (
{ label, url }) – utöver oder istället för uppladdade filer, till exempel för datablad på den egna webbplatsen. - API:
POST/PATCH /v1/codesaccepterar enlinks-array (0–20 poster,http(s), ≤ 2048 tecken). Varje URL kontrolleras med Google Web Risk; en osäker URL returnerar422. En tom array tar bort alla länkar. - Dashboard: Lägg till, sortera och ta bort länkar på koddetaljsidan.
- Säkerhet: Renderade länkar förblir XSS-säkra (escaped, endast
http(s)) och sidan behåller sinnoindex-header.
2026-04 · Dashboard-analys per QR-kod
- Dashboard: Analysknappen i QR-kodlistan öppnar nu statistik-sidan för respektive QR-kod under
/dashboard/codes/{id}. - Routing: Aliaset
/dashboard/codesomdirigerar fortfarande till/dashboard, men fångar inte längre upp detaljerade rutter som/dashboard/codes/{id}. - API: Detaljsidan läser in QR-koden direkt via
GET /v1/codes/:id; därmed är den inte längre beroende av pagineringsgränser för listor. - Tester: Regressionstester täcker alias-omdirigeringen och den direkta inläsningen av koden.
2026-04 · Dashboard-borttagningsdialog för QR-koder
- Dashboard: Papperskorgen i QR-kodlistan öppnar nu en egen React-dialogruta istället för en inbyggd popup i webbläsaren.
- Feedback: Efter borttagning visas ett toast-meddelande för framgång eller fel.
- Tester:
packages/dashboard/tests/dashboard.test.tsförhindrar regressioner förconfirm()i QR-kodens borttagningsflöde.
2026-04 · Dashboard-kortlänkstest för dynamiska QR-koder
- Dashboard: Shortcodes in QR-kodlistan är nu direkt klickbara som externa omdirigeringslänkar. Ikonen för extern länk bredvid t.ex.
wu3qaaöppnarhttps://qr3.app/{shortCode}i en ny flik. - i18n: Tooltip-texter för tyska och engelska har lagts till.
- Tester:
packages/dashboard/tests/dashboard.test.tsskyddar länk-href, beteende för ny flik,noopener noreferreroch ikon mot regressioner.
2026-04 · Redirect-Worker-rutt för dynamiska QR-koder
- Fix: Dynamiska QR-koder under
https://qr3.app/{shortCode}hanteras återigen av omdirigerings-workern. Produktionsrutten använder nuqr3.app/*eftersom Cloudflare Workers rutter inte stöder:code-sökvägsparametrar. - Härdning: Sökvägar som inte matchar skickas vidare till landnings-origin, så att vanliga sidor som
/de/pricinginte blockeras av omdirigerings-workern. - Tester:
packages/redirect/tests/unit/redirect.test.tstestar wildcard-rutten, shortcode-bearbetningen och origin-pass-through.
2026-04 · Workspace-DPP-skanningsöversikt (Q3.4.2)
- Nytt:
GET /v1/workspace/stats/dpp?days=30— aggregerar alladpp_scansför API-nyckelns workspace (active_dpps,scans_by_day,top_dppsmed produktnamn/kategori). - Dashboard: Kort på startsidan (
/dashboard) med 30-dagars stapeldiagram + topplistor — parallellt med QR-kodkorten. - Public: Marknadsföringskortlänk
GET /dpp/dpp_<id>(ett segment) för livedemos, parallellt med/dpp/{gtin}/{serial}.
2026-04 · DPP-skanningsanalys (Q3.4.1)
- Nytt:
GET /v1/dpp/:id/stats?days=30— aggregerade skanningar från den offentliga GS1-resolveraren per DPP. Fält:total_scans,period_scans,scans_by_day,top_countries,top_devices,top_representations. - Nytt: Tabellen
dpp_scans(migrering0011) — separerad frånscans(omdirigerings-worker). IP-adresser hashas med ett dagligen roterande salt, råa IP-adresser når aldrig D1. - Dashboard: Mini-diagramkort (SVG, inget diagrambibliotek) på
/dashboard/dpp/:dppIdmed 30-dagarsstaplar + topp 3-uppdelningar. Empty-state så snart en DPP är live men ännu inte har haft några skanningar.
2026-04 · Live-EU-efterlevnadssimulator (Q3.3.7)
- Nytt:
POST /v1/dpp/:id/validate-update— simulerar delvisa uppdateringar stateless (status, marknadslista, …) utan persistens. Svaret innehållereu_compliance+preview.changed_fields. - Dashboard: Simulatorkort i DPP-detaljvyn (
/dashboard/dpp/:dppId) — chips förDE/AT/FR/IT/ES/NL+ anpassad, status-rullgardinsmeny, Preview EU impact / Save changes / Reset. Icke-blockerande via RemixuseFetcher. - Härdning: Utbrutna simulatorhjälpare (
readUpdatePatchFromForm,marketCountriesKey) + 18 nya enhetstester; buggfix: Enstaka icke-ISO-indata tömmer inte längre marknadslistan.
2026-04 · Live-EU-efterlevnadsförhandsvisning i skapa-formuläret (Q3.3.6)
- Ändrat:
POST /v1/dpp/validatereturnerar nu äveneu_compliance— samma validerare somGET /v1/dpp/:id/eu-compliance, stateless före sparning. - Dashboard: Förhandsvisning under den befintliga valideringspanelen + ny Save-Guard-banner före skicka-knapparna om det finns öppna fel/varningar (i18n-pluralisering DE/EN).
2026-04 · EU-validerare + textil-UI (Q3.3.4 + Q3.3.5)
- Nytt: EU-efterlevnadsvaliderare med 5 textilregler (
TEXTILE_AGEC_REQUIRED,TEXTILE_MICROPLASTICS_CONSISTENCY,TEXTILE_SVHC_THRESHOLD,TEXTILE_GREENWASHING,TEXTILE_ESPR_READY). - Nytt:
GET /v1/dpp/:id/eu-compliancemedcompliant/espr_ready/issues[]/summary. - Dashboard: EU-efterlevnadssektion i DPP-detaljvyn (sammanfattningskort, grupperade problemkort, ESPR-Ready-badge i headern).
2026-04 · Textil-DPP-schema (Q3.3.1–Q3.3.3)
- Nytt: Kategorin
textilemed obligatorisk AGEC-kedja (vävning/stickning → färgning/tryckning → konfektion), per fiberorigin_country+recycled_pct,svhc_substances[], ESPR-opt-in (PEF, livslängd, återvinningsbarhet). - Nytt: Basfältet
market_countries: string[](ISO 3166-1 alpha-2) på alla DPP-kategorier — styr FR-specifika AGEC-regler och det franska obligatoriska konsumentmeddelandet. - Nytt: Konsument-HTML-mall med AGEC-mikroplastvarning, ursprungskedja i 3 steg (flaggpiller), SVHC-lista samt sektioner för hållbarhet och återvinningsbarhet.
- Migrering:
0010_dpp_market_countries(D1).
2026-04 · DPP-massimport (Q3.2.1–Q3.2.5)
- Nytt:
POST /v1/dpp/importaccepterar CSV och XLSX (Worker-kompatibel via SheetJSxlsx, ~283 KB gzip-bundle). - Skalat: abonnemangsbaserad gräns (Free 100 → Enterprise 10k) + uppdelad
db.batch()à 100 + 5 MB body-gräns. - Nytt: Felrapport som CSV i fältet
errors_csvi 201-svaret;GET /v1/dpp/import/templates/:category?format=csv|xlsxlevererar färdiga mallar för batteri och textil. - Dashboard: Dra-och-släpp-uppladdning under
/dashboard/dpp/importmed mall-proxy och inline-CSV-nedladdning.
Icke-brytande — LTS-utökningar
Alla ovan nämnda ändringar är additiva:
- Befintliga
POST /v1/dpp/validate-klienter ignorerar det nyaeu_compliance-fältet utan ändringar. - Befintliga
battery-flöden är oförändrade. market_countriesär valfritt och har standardvärdet[].
Se API-versionering för policyn gällande brytande ändringar.