Changelog
How Veridyn has evolved, month by month — from the first version of the product passport engine to the developer API. Dates indicate the month a feature shipped; material changes are logged here.
Contact messages now expire too
An enquiry submitted through the contact form (name, email, company, message) used to sit in the admin inbox with no expiry, while the Privacy notice showed only an “e.g. 1 year” marker in its place. Enquiries are now deleted automatically after 24 months, carried out by the same scheduled clean-up that handles the scan log — and the notice states that number rather than a placeholder. The form itself now carries the short notice too: what we use the message for, on what legal basis, and how long we keep it.
Certificate upload and supplier requests from code
Two features were until now available only from a browser, though the machine route is exactly where they are needed. Document upload: a certificate PDF originates in a document management system or in correspondence with a lab, not in a browser tab — it can now be uploaded in base64, downloaded and deleted through the API. The type is decided by the content, not the file name: a file merely named as a PDF is rejected. Supplier data requests: starting the link that asks the mill or the cell maker for their data, reviewing the submission and merging it all work from code — so a procurement system can start the 500 data requests, not just upload the 500 passports.
Incremental sync: changes only
An ERP cannot re-read the whole passport inventory every night. With the <code>updated_since</code> parameter you now get back only the changed passports — at every level (model, batch, unit) — with cursor-based paging. A cursor rather than a page number: page-number paging silently skips rows when an already-seen item is modified in the meantime. Archived passports are not filtered out either: they arrive with an <code>archived</code> status, so your system knows to drop them.
Lifecycle, versions and authority access from the API
What was previously possible only in the UI now works from code as well: archive and restore (without generating a version — a visibility change is not a data change), the change history with a field-level diff, and issuing expiring access links for an authority or a party with legitimate interest. The last of these deliberately has no plan gate: authority access is a legal requirement, not an upsell.
PATCH now tells you what it dropped
The <code>PATCH /products/{id}</code> endpoint merges by top-level key. So if you send a nested object (for example <code>dimensions</code>) only partially, the sibling fields you omitted are lost — and where the object has no required sub-field, the save used to succeed while the data silently disappeared. We deliberately did NOT change the behaviour (replacing a whole object can be intentional, and switching to a deep merge would retroactively break existing calls), but the response now says so: <code>dropped_fields</code> lists what was dropped, along with a <code>warning</code>. The previous version stays intact in the change history, so it can be restored.
Standard terms in a unit passport’s machine data
A unit passport’s machine output was missing the GTIN — a machine had to fetch the parent passport as well to learn which product the unit belongs to. Its type was <code>Product</code>, although schema.org’s <code>IndividualProduct</code> means exactly this: “a single, identifiable instance of a product”. And the serial number and the modification date appeared only under our own <code>dpp:</code> terms, not under the standard <code>serialNumber</code> and <code>dateModified</code>. All four are fixed, and additively: the existing <code>dpp:</code> fields stayed where they were and the standard ones joined them — no current integration breaks.
Unknown serial: we say we could not find it
When someone scans a batch or serial number that does not exist — a typo, a damaged QR code or a counterfeit — the system used to silently return the model passport. That is the worst possible answer: it looked like a valid product passport. It now returns the nearest known level and warns at the top of the page that the scanned identifier was not found. Machine requests get a <code>404</code> with an <code>unknown_identifier</code> code and the model URL, and the page is marked <code>noindex</code> so a bogus identifier never reaches search engines.
You can see it when we entered your account
Support sometimes has to enter an account. That always went into an append-only log — but on our side, where you could not see it. And a promise you cannot verify is not a promise. Your own log is now in Settings: when we entered, when we left, how long it lasted. We deliberately do not name the staff member — that is our internal accountability — but the fact and the duration are yours. In addition, every version we saved while inside your account is marked in the change history, so it stays visible afterwards that you did not write it. As part of this we also fixed logging out: it now closes the entry on every path — an unclosed row used to show “still inside” forever.
Import now returns a spoken error for oversized files
A large or corrupted spreadsheet used to hit the server’s memory limit, and the browser received only a broken response — nothing said what was wrong. Uploads are now checked at three points: the file size (at most 16 MB), the number of internal entries in the workbook, and the uncompressed size (at most 32 MB). In all three cases you get a proper, explanatory error that also states the limit. For a large inventory, split it into several files — the import can be run repeatedly.
Units of measure are now machine data
A number on its own is not data: <code>ratedCapacity: 2500</code> could be 2500 Ah or 2500 mAh, and the difference is a factor of a thousand. Until now the unit lived only in the human field label — the schema endpoint never reported it. Every numeric field now also returns a <code>unit</code> (<code>GET /api/v1/schema/{category}</code>), and the <a href="/ns/dpp/v1">vocabulary page</a> lists it too. The most important case is the carbon footprint: for batteries it is normalised per energy (<code>kg CO₂e/kWh</code>), for textiles per item (<code>kg CO₂e</code>) — the same field name, incomparable numbers. Nothing signalled this before.
Schema version: we now signal contract changes
A category's field list moves with the legislation, and until now nothing signalled a change — integrations broke silently. The schema endpoint now returns a version and an ETag: as long as you get a <code>304</code>, there is nothing to do. The fingerprint is built from the machine contract (field, type, requiredness, enum, access tier), so rewording a label or a help text raises no false alarm. For backwards-incompatible changes, <code>Deprecation</code> and <code>Sunset</code> headers are sent as well.
Writing live unit data back in bulk
Some unit-level fields are live data: a battery's state of health, cycle count and remaining capacity come from the BMS. These can now be written back to up to 500 unit passports in a single call, addressed by serial or lot number — you need not store our internal identifier. Where a value did not change, no empty version is created: a daily fleet sync does not fill the change history with noise.
GTIN ownership protection
A GTIN is built from the manufacturer's GS1 company prefix, and a product identifier in someone else's account produces a misleading passport. You can now enter your own GS1 company prefix: the system will not let you record a GTIN outside it. For accounts without a prefix, range validation remains (excluding in-store, coupon and demo ranges), and any disputed identifier can be reported — without a login.
Webhooks: identified events, catch-up, resend
Retrying means the same event can arrive more than once. Every event therefore gets its own identifier (in the signed body and in a header), which makes deduplication possible. If your system was unreachable for a long time, the event used to be lost — now the full event history can be queried, with delivery status, and you can continue from where you left off.
BatteryPass conformance: 11/11
We pass all 11 tests of the BatteryPass-Ready conformance suite — repeated three times in a row so that luck does not decide. The suite does not inspect a submitted file: it addresses the running system over the network and measures whether it behaves as the standard requires — reading by passport and product identifier, field-by-field access filtering, versioned updates, adding and deleting attributes, withdrawn passports, permission checks, and reporting the placing on the market.
Full JTC24 coverage
We can emit every mappable field of the official EV data model. We had to measure it, because a schema validator never answers this question: previously 129 out of 211 fields went out, that is 61% — fourteen field groups simply did not exist in our schema (absolute carbon footprint, certified and remaining usable energy, cadmium/lead marking, warranty period, date of putting into service, overcharge and deep-discharge events, supply-chain risk indices, recycled content per material). Coverage is now guarded by a test so it cannot regress silently.
Standards-based machine interface
Alongside our own developer API we now serve the endpoints of the CEN-CENELEC JTC 24 lifecycle API (EN 18222) — in the language the rest of the battery ecosystem speaks. With role-based access, and with the outbound calls that placing on the market requires: a copy to the independent backup provider, then the registry notification — in that order, because the notification asks for the backup identifier.
Legal completeness before saving
“Saveable” and “legally complete” are two different things: the first is the handful of fields without which there is no meaningful record, the second is what penalties are based on. The editor now warns before saving if a passport is legally incomplete — showing the percentage, the missing fields and the legal basis. It does not block, because data often accumulates in stages, but it no longer lets a passport go out silently. The compliance dashboard shows technical validity and legal completeness in separate columns.
Importing a foreign battery passport
A JTC24 document received from another provider can now be imported, edited and returned unchanged. Its fields are mapped onto ours; anything we have no field for is preserved untouched and handed back in the export. This is what makes switching providers practical: exporting the data is not enough, the other side has to be able to read it — and the other way round.
Field counts per section
A battery passport has a great many fields. Every section header now shows how many fields it holds, how many of those are needed to save, and how many are legally required — so you no longer have to open each section to find where work remains.
Download any version
Every passport version is captured as an immutable, hash-stamped snapshot. Any of them can be downloaded as JSON from the version history — taking your data out is now one click, not a promise. Market surveillance can reach it too, via the authority access link.
The full chain from the interface
An individual unit can now be created directly under a production batch — it inherits the batch identifier, so the printed QR resolves the full model → batch → unit chain. Batch and unit passports can also be archived and restored at any time: there is no delete, because a printed QR must never return a 404.
Unlimited batch & unit passports
Plans now meter only the number of model passports: production-batch and individual-unit passports are unlimited on every paid plan (fair use). Which level you need is decided by the regulation that applies to you — the Battery Regulation mandates unit level from 18 February 2027 — not by our price list.
Out-of-date unit passport alerts
Batch and unit passports keep a snapshot of the model data as it stood at creation (this is what makes the hash chain provable). We now track which model version each came from: if you later correct an error on the model, the system reports how many issued passports went out of date, and all of them can be refreshed in one click. But if the product itself changed (e.g. a new supplier), the data of earlier units is left untouched — it is correct for its time.
Open beta program
Anyone can join: every feature free up to 100 model passports, with no per-account time limit. When the beta ends, early accounts receive a lasting founder discount.
Developer REST API + interactive reference
OpenAPI 3.1 spec, a downloadable Postman collection, scoped keys (full or read-only), per-minute rate limits, idempotency keys, plus signed and automatically retried webhooks — with a browsable, searchable API reference.
Counterfeit-clone alerts
If a single serialised product’s QR is scanned from many different countries — unusual for a single physical item — the system flags a suspected clone (alert + webhook).
Data portability & continuity
Export at any time (JSON-LD / GS1 Digital Link) with no export lock-in, and a continuity guarantee — your QR codes stay alive even if you leave.
EU DPP Registry readiness
Commodity (CN) code field, “registry-ready” indicators, and a step-by-step eIDAS verification guide for the central EU registry.
Layered access + shareable tokens
Public / legitimate-interest / authority tiers, with shareable, expiring access links — control over sensitive data stays with you.
Supplier data intake
Request data and documents from your suppliers via a no-login, expiring link, then merge it into the product with one click.
Document vault + hash chain
Attach compliance documents (certificates, datasheets) to the passport, and a cryptographic hash chain is built for every version — provably unchanged data.
Scan analytics
Scan statistics by country, device and time on the dashboard, with milestone webhooks — see where and when your products are viewed.
24 EU languages on the passport
The public product passport renders in all 24 official EU languages, adapting to the visitor — a key-based translation engine, not machine mistranslation.
Knowledge base + DPP readiness test
Data-driven guides on DPP regulation (ESPR, deadlines, penalties), and a free readiness test that shows where you stand on compliance.
Live, hands-on demo
A no-signup demo account seeded with sample data — so you can see how the system looks and works before registering.
Billing system (inactive during beta)
Free / Starter / Pro / Business / Enterprise plans, a trial period, Stripe Embedded Checkout, VAT handling, and extra passport quota beyond your plan — built, but inactive during the beta (everyone gets free full access).
Admin console
Internal operations console: operational metrics, logged support access, a message inbox and account management in one place.
Email notifications + password reset
Welcome and contact emails, plus secure password reset — over our own SMTP with reliable delivery.
Versioned passports + change history
Every change creates a new version with full change history and an “updated” date — the passport is always auditable.
Guided passport editor
A completeness ring, a section-based form and “start here” markers — filling the required EU fields step by step, hard to get wrong.
Multi-format bulk import
Bulk-import products from CSV, XLSX, JSON and XML with automatic field mapping — a large catalogue in minutes.
The product passport engine
Veridyn launches: schema-driven EU digital product passports with no code — category templates (battery, textile, furniture…), a QR code and a passport page for every product.
GS1 Digital Link + JSON-LD + unified theme
A standards-based public passport: GS1 Digital Link URLs, JSON-LD structured data for search engines and machines, and a unified light/dark theme.