---
title: "Changelog · Quittio"
description: "What’s new in Quittio, version by version, straight from CHANGELOG.md on GitHub."
canonical_url: "https://quittio.dev/en/changelog"
locale: en
meta:
  "og:description": "What’s new in Quittio, version by version, straight from CHANGELOG.md on GitHub."
  "og:image": "https://quittio.dev/og/quittio-en.jpg"
  "og:image:alt": "Quittio: Invoices, settled. E-invoicing for PHP and Laravel, with a validated sample invoice."
  "og:image:height": "630"
  "og:image:type": image/jpeg
  "og:image:width": "1200"
  "og:title": "Changelog · Quittio"
  "twitter:image": "https://quittio.dev/og/quittio-en.jpg"
  "twitter:image:alt": "Quittio: Invoices, settled. E-invoicing for PHP and Laravel, with a validated sample invoice."
---

> Index of every page on this site: [llms.txt](https://quittio.dev/llms.txt)

# Changelog

What’s new, version by version, straight from CHANGELOG.md on GitHub.

[**CHANGELOG.md**](https://github.com/Quittio/quittio/blob/master/CHANGELOG.md)

## **0.3.0**

**Latest**

16 Oct 2026

[**Release on GitHub**](https://github.com/Quittio/quittio/releases/tag/v0.3.0)

### Added

- Single PHP rules can be switched off, re-rated or replaced by their code: `validation.rules.disabled`, `validation.rules.severity` and `Quittio::extend('rule', …)` in Laravel, `RuleOverrides` with `Quittio::configureRules()` in the core. Official EN 16931 and Peppol rules need `allow_official`; unknown codes are refused. `Quittio::ruleCodes()` lists the known codes.
- The calculation policy decides what happens with declared amounts of other systems: `calculation.declared_amounts` ( `keep`, `recalculate`, `reject`), `CalculationPolicy` and `DeclaredAmountsMode` in the core. An own calculator is configured with `calculation.calculator` or passed to `Quittio::create(calculator: …)`; `Quittio::calculator()` returns it.
- `Quittio::edit()` (core and Laravel) and `InvoiceBuilder::fromUsing()` continue existing invoice data with the calculator of the instance; cancellations and the document calculator of `QuittioFake` use it as well. `InvoiceFactory::calculated()` takes a calculator.
- Tax presets whose rate depends on the date ( `Quittio\Core\Tax\DatedTaxPreset`) are resolved with the supply date of each line ( `SupplyDate`: line period, VAT point date, delivery date, invoicing period, issue date). `DatedValues` holds values that change on dates; `TaxPresetCollection::alias()` finds presets under further keys.
- `VatPreset::Standard` ( `de.standard`) and `VatPreset::Reduced` ( `de.reduced`) take the German rate of the supply date ( `TaxTables`), e.g. 16 % and 5 % from July to December 2020. The plausibility rule `DE-VAT-RATE` warns about rates that applied neither as standard nor as reduced rate on the supply date. The small amount limit of `DE-USTG-08` is that of the issue date (150.00 EUR before 2017).
- Country packs register output formats, aliases and serializers ( `Countries\Capabilities\ProvidesFormats`, implemented by `AbstractCountryPack`); the German pack brings XRechnung ( `XRechnungFormats`). Profiles declare sub lines, extension fields and third party payments with capabilities ( `SupportsSubLines`, `SupportsExtensionFields`, `SupportsThirdPartyPayments`) instead of the core checking XRechnung keys.
- Default interest for every country pack with a reference rate: `Quittio\Core\Dunning\DefaultInterest` ( `forCountry($pack)`), the contract `Dunning\ReferenceRates` and the capability `ProvidesReferenceRates`; the German pack provides its base rates ( `BaseRateTable` implements `ReferenceRates`) and its `DefaultInterest` uses the core calculation. `DocumentBuilder::interestCharge()` adds calculated charges with their day count and texts.
- Documents can be queued in Laravel: `Quittio::document($quote)->queue()->save($disk, $path)` with the job `RenderDocument`, the events `QueuedDocumentStored` and `QueuedDocumentFailed` and `QuittioManager::queueDocument()`; `QuittioFake` records them ( `assertDocumentQueued()`, `queuedDocuments()`). Documents are stored as versioned snapshots ( `DocumentData::toSnapshot()`, `fromSnapshot()`, `toArray()`, `toJson()` …) with their own upcasters ( `quittio.snapshots.document_upcasters`, `SnapshotUpcasterChain::documentDefault()`); `Mapping\Attributes\MapOf` keeps keyed arrays.
- The German special cases are reached with the builder macro `de()`: `->de()->smallAmount()`, `->de()->selfBilled()`, `->de()->deductAdvance($advance)` … ( `GermanInvoice`).

### Changed

- Lines without VAT treatment of a German seller get the preset key `de.standard` instead of `de.standard_19`, and `quittio.defaults.vat = 'de.reduced_7'` gives `de.reduced`. Applications that compare preset keys use `VatPreset::fromKey($key)?->canonical()`. Supplies from 2020-07-01 to 2020-12-31 get 16 % and 5 %.
- `CiiWriter`, `UblWriter`, `CiiReader` and `UblReader` keep no state between calls: each call works with its own internal worker, so one instance can be used reentrantly. The readers no longer extend the internal `XPathReader` and therefore no longer expose its constants.
- The render run resolves the logo of the presentation before it builds the view model ( `ViewContext::$logo`, `ResolvedLogo`), so the view layer does no I/O; `ViewModelFactory` keeps no state between calls.
- The documentation website is versioned: the root shows the latest release, `/next/` the development version and `/X.Y/` older minor versions, with a version switcher ( `docs/_versioning/build.mjs`). Every version has a generated API reference under `api/` (phpDocumentor, `tools/docs/phpdoc.sh`); the builder traits under `Builder\Concerns` are no longer `@internal`, so their methods appear there.
- Pull requests opened in the read-only split repositories `quittio/core`, `quittio/laravel` and `quittio/country-de` are closed automatically with a pointer to the monorepo.

### Deprecated

- `VatPreset::Standard19` and `VatPreset::Reduced7`: use `VatPreset::Standard` and `VatPreset::Reduced`; the keys `de.standard_19` and `de.reduced_7` stay readable. `Flags::SMALL_AMOUNT_LIMIT`: use `TaxTables::smallAmountLimitOn()`.
- The builder macros `smallAmount()`, `propertyRelatedService()`, `newVehicle()`, `selfBilled()`, `deductAdvance()` and `consumerDefaultNotice()` directly on the builder: use `->de()->…`. `GermanInvoiceMacros::ADVANCE_TYPES`: use `GermanInvoice::ADVANCE_TYPES`. `FormatRegistry::XRECHNUNG_CII` and `XRECHNUNG_UBL`: use `XRechnungFormats::CII` and `UBL` of the German pack, which registers the formats; the core keeps them until 1.0.

### Fixed

- Peppol invoices with an electronic address scheme that Peppol does not accept, e.g. `EM` (e-mail), are rejected with the new rule `PEPPOL-EN16931-CL008` instead of passing the PHP rules and failing the official Peppol validation. The allowed schemes are the code list `CodeList::PEPPOL_EAS` ( `peppol-eas-codes.json`, from the Peppol BIS rules 3.0.20); `tools/codelists/update.php` regenerates it with `CodeListGenerator::generatePeppol()`.

## **0.2.0**

16 Oct 2026

[**Release on GitHub**](https://github.com/Quittio/quittio/releases/tag/v0.2.0)

### Added

- The legal texts of the German pack ( `LegalTexts`) and the text of default interest come from its language files ( `resources/lang/{de,en}/legal.php`), so `lang/vendor/quittio-de` overrides them in Laravel; `LegalTexts::DEFAULT_INTEREST` is new.
- `quittio/country-de` ships `stubs/InvoiceBuilder.stub.php`, which describes its builder macros ( `smallAmount()`, `selfBilled()`, `deductAdvance()`, …) for IDEs and PHPStan.
- Tests: generated round trips through CII and UBL, fuzzing of the XML, PDF and array input, and tests for formats, mapping, serialisation, the PDF parser, mail attachments, a second boot and the escaping of the Blade templates.
- Documentation: [Versioning and compatibility](https://github.com/Quittio/quittio/blob/master/docs/compatibility.md) with the backwards compatibility promise; `ARCHITECTURE.md`, decision records in `docs/adr/`, `RELEASING.md`, a reworked `CONTRIBUTING.md`, an FAQ page; issue and pull request templates, `CODEOWNERS` and response times in `SECURITY.md`. Classes outside the public API ( `XPathReader`, `XmlBuilder`, `Pdf\Parsing`, `CarryOver`, `ConfigMapper`, the command and preview classes, …) are marked `@internal`.
- Documents (quotes, reminders, …) dispatch `DocumentRendering` and `DocumentRendered` in Laravel; `PendingDocument` has `option()` (core and Laravel), `data()`, `options()` and is `Macroable` (Laravel).
- `Quittio::setPostProcessor()` replaces the PDF/A and XML embedding for renderers that cannot embed. Profiles describe their embedded XML with the capability `DescribesEmbeddedXml` (XMP description and `fx:Version`) instead of the file name deciding it.
- Amounts of `prepaid()`, `addPrepaid()`, `rounding()`, `discountPercent()`, `discountAmount()` and of the document builder's `fee()` and `openingBalance()` accept `BigDecimal`, `int` or `string` like line prices (floats are rejected). `DocumentBuilder::note()`, `discountPercent()` and `discountAmount()` take the same subject and reason codes as the invoice builder.
- `QuittioFake` dispatches the events of a real run ( `InvoiceRendering`, `InvoiceValidated`, `InvoiceRendered`) and records queued invoices: `assertQueued()`, `assertNothingQueued()`, `queued()`. Its decisions follow configuration changes without `Quittio::flush()`.
- Events `QueuedInvoiceStored` (a queued job stored the file, with disk and path) and `QueuedInvoiceFailed` (a queued job failed for good).
- `Quittio\Core\Quittio::resetState()` forgets the process-wide state (translator bridge, default snapshot upcasters, application default VAT, base rates of the German pack); extensions register their own state with `onResetState()`. The test trait `InteractsWithQuittio` calls it after each test.

### Changed

- README and documentation mark the Managed layer `quittio/managed` as not released yet; its documentation page is a preview and is left out of `llms.txt`, `llms-full.txt` and the MCP index.
- The documentation is built and link-checked on pull requests; every PHP code block of the documentation must parse.
- `quittio/core`, `quittio/laravel` and `quittio/country-de` declare their test dependencies and ship a `phpunit.xml.dist`, so their split repositories run `composer test` on their own.
- `quittio/quittio` registers the `Quittio` facade alias and suggests `ext-intl`, `ext-zip` and `opis/json-schema` like the single packages.
- Development: Composer scripts `test:fast`, `test:official`, `test:visual`, `test:coverage`, `test:mutation`, `docs:generate`, `codelists:update` and `ci`; a weekly CI run with `composer audit`, line coverage and mutation testing; PHPStan also checks `tools/*.php` and reports calls of deprecated code.
- Visual baselines are written only with `QUITTIO_UPDATE_BASELINES=1`; a missing baseline fails the test. The default Blade partials that print pre-escaped HTML carry a warning comment.
- Queued `RenderInvoice` jobs store the render options as versioned JSON ( `RenderOptions::toArray()`/ `fromArray()`) instead of a PHP-serialised object, so an update of Quittio no longer breaks jobs in the queue; jobs queued by 0.1.0 still run. Errors that another attempt cannot fix (validation, invalid data, configuration) fail the job at once instead of three times; other errors are retried after 10 and 60 seconds. Inside a database transaction the job is dispatched after the commit ( `quittio.queue.after_commit`).
- Every exception that Quittio throws implements `QuittioException`: invalid arguments and runtime errors are now `Quittio\Core\Exceptions\InvalidArgumentException`, `RuntimeException` or `LogicException`, which extend the PHP classes of the same name, so existing `catch` blocks keep working.
- Country pack discovery keeps its result in `bootstrap/cache/quittio-countries.php` (and per process) until Composer changes the installed packages, instead of reading `vendor/composer/installed.json` whenever the core is built.
- The Laravel configuration no longer defaults to Germany: `defaults.country` ( `QUITTIO_COUNTRY`) and `seller.address.country` are `null`, which means the only installed country pack (Germany with `quittio/quittio`), so existing applications keep their behaviour. With several packs, set `defaults.country` or the seller's country. `Quittio::registerCountry()` makes the next call build the core again.
- The Laravel manager builds a new core when the `quittio` configuration changes, so `Quittio::flush()` is no longer needed after `config()->set()`. Under Octane it reads the configuration of the current request instead of the application that created the singleton; so does the default VAT of lines without VAT.

### Deprecated

- Environment variables are named after their configuration keys: `QUITTIO_DEFAULT_COUNTRY`, `QUITTIO_VALIDATION_MODE`, `QUITTIO_MANDATORY_FIELD_GUARD`, `QUITTIO_STORAGE_DISK` and `QUITTIO_PREVIEW_ENABLED`. The names of 0.1.0 ( `QUITTIO_COUNTRY`, `QUITTIO_VALIDATION`, `QUITTIO_GUARD`, `QUITTIO_DISK`, `QUITTIO_PREVIEW`) are still read when the new one is not set, until 1.0.
- The methods of `Quittio\Core\Quittio` that change the instance are named after what they do: `addSerializer()`, `addValidator()`, `clearValidators()`, `setRenderer()`, `setTemplateEngine()`, `setPaymentQrGenerator()` and `setFormatResolver()`. The `with…()` names, which elsewhere in Quittio return a changed copy, remain as deprecated aliases until 1.0.

### Security

- `quittio:schemas:download` checks the KoSIT validator, the XRechnung configuration, the Peppol rules and SchXslt against pinned SHA-256 checksums before it unpacks or runs them; so do the download scripts in `tools/`.
- Decimal strings are only accepted in plain notation ( `Decimal::of()`, builders, `InvoiceData::fromArray()`/ `fromJson()`, snapshots): an exponent such as `1e999999999` was expanded to a billion digits and exhausted the memory. Other notations throw a `NumberFormatException` (a `HydrationException` for array and JSON input).
- The preview route refuses requests outside the `local` environment unless the gate `viewQuittioPreview` allows them; before, `QUITTIO_PREVIEW=true` made it public behind the `web` middleware only. Requests are limited to 30 per minute ( `quittio.preview.throttle`). `QuittioServiceProvider::registerPreviewRoutes()` is no longer public.

### Fixed

- Default interest of payment reminders was described in English for German locales with a region such as `de_AT`.
- `InvoiceData::fromJson()` threw PHP's `JsonException` for JSON that cannot be parsed (empty, too deep, invalid UTF-8); it now throws a `HydrationException`. `JsonSchemaValidator::validate()` reports such input as a finding.
- `DE-USTG-08` names the limit of `Flags::SMALL_AMOUNT_LIMIT` (250.00 EUR) instead of a second, hard-coded value. The English fallback messages of four UStG rules matched their translations no longer; a test now compares every rule's fallback with `lang/en/rules.php` and requires a German message.
- The field reference documents the UBL credit note path of BT-129 and BT-130 ( `cbc:CreditedQuantity`) and no longer shows pseudo-XPath for BT-110 and BT-111. A test now evaluates every documented CII and UBL path against the XML of the sample invoices and of the official XRechnung test suite.
- A custom `TotalsCalculator` was bypassed by the VAT alignment of partial cancellations; `Cancellation::of()` and `DeclaredAmounts::needed()` accept the calculator, and `Quittio::cancellation()` passes its own.
- Texts with control characters (e.g. a vertical tab copied from a spreadsheet cell) or invalid UTF-8 produced XML that was not well-formed and was rejected by every receiver. The new rule `QUITTIO-INVALID-CHARACTERS` names the field, and the CII and UBL writers refuse such data with an `InvalidInvoiceData` exception.
- A UBL credit note without payment instructions (BG-16) left out its due date (BT-9) silently: the UBL binding transmits it only in `cac:PaymentMeans`. The new warning `QUITTIO-CREDIT-NOTE-DUE-DATE` points this out; the field reference names the credit note path.
- A percentage document allowance or charge without base amount whose VAT category and rate matched no invoice line became 0.00 silently (data from JSON, readers or `with()`); the calculator now throws a `CalculationException`. Drafts without any lines still calculate with a zero base.
- Reading an invoice and the check for declared amounts no longer turn errors such as a `TypeError` of a custom `TotalsCalculator` into the warning `QUITTIO-READER-RECALCULATION`; only exceptions are reported.
- The post-processing of PDFs from renderers that cannot embed (PDF/A and XML) uses the configured `temp_dir` instead of the system temporary directory.
- `quittio:validate`: an unknown `--profile` printed a stack trace; files that cannot be checked (missing, not an e-invoice, unknown profile) now exit with `2` instead of `1`, so scripts can tell them from invalid files; with `--json` such errors are printed as `{"valid": false, "error": …}` and the result names `expectedProfile` and `profileMismatch`.
- Failed writes are reported with a clear message: `quittio:render`, `quittio:preview` and `quittio:base-rate:update` exit with `1`, `RenderedInvoice::save()` of the Laravel package throws a `RuntimeException` when the disk does not store the file. `save()` of the core results and `quittio:render --output` treat a path ending in `/` as directory and create missing directories ( `RenderedDocument::save()` did not create them).
- The CII and UBL readers accept every `xs:boolean` spelling of `ChargeIndicator` ( `1`/ `0`, surrounding white space). Before, such document allowances and charges were dropped and line charges were read as allowances; a missing or invalid indicator is now reported as `QUITTIO-READER-CHARGE-INDICATOR`. The documented CII and UBL paths of BG-20 and BG-21 are valid XPath.

## **0.1.0**

15 Oct 2026

[**Release on GitHub**](https://github.com/Quittio/quittio/releases/tag/v0.1.0)

First release.

### Added

- Monorepo `quittio/quittio` (the complete package) with the read-only splits `quittio/core`, `quittio/laravel` and `quittio/country-de`.
- EN 16931 data model with mapping attributes (BT, cardinality, profile level, CII and UBL paths), builders, JSON conversion, generated JSON schema and field reference.
- Calculation according to EN 16931 including document allowances split by VAT rate, gross prices, foreign currency and third party payments.
- Profiles MINIMUM, BASIC WL, BASIC, EN 16931, EXTENDED, Peppol BIS 3; XRechnung 3.0 and the XRechnung extension in the country pack Germany.
- Validation levels L1 to L7: PHP rules (EN 16931, Peppol, BR-DE, UStG), XSD, KoSIT validator (daemon and CLI), veraPDF (CLI and Docker), plausibility checks.
- CII and UBL writers and readers with protection against XXE, entity expansion and oversized input; PDF reader for embedded invoices with decompression limits.
- ZUGFeRD/Factur-X PDF/A-3b with mPDF, XMP metadata and associated files; post processing of foreign PDFs; EPC GiroCode.
- View model with formatted and raw values, mandatory field guard, plain PHP and Blade default templates with partials, DIN 5008 letter layouts.
- Format resolver, entry point `Quittio\Core\Quittio` and Laravel facade with several formats per call, storage, downloads, mail attachments, queue, events, preview route and Artisan commands.
- Quotes, order confirmations, delivery notes, proforma invoices, payment reminders and account statements.
- Country pack Germany: tax presets, UStG rules, format rules, legal texts, BMF error classes, numbering, retention, dunning law with base rate table, correction policy, builder helpers.
- Testing helpers: fake, assertions, invoice factory, sample scenarios, visual regression (identical baselines on macOS and the Linux CI image).
- `quittio:schemas:download` compiles the Peppol BIS Billing 3.0 rules; KoSIT configuration accepts several scenario sets.
- Base rates up to 1 July 2026; small business invoices according to section 34a UStDV.
- Full cancellations ( `Quittio::cancellation()`) with configurable sign strategy: type code 381 with positive amounts (default) or 380 with negative amounts ( `corrections.cancellation_strategy`).
- `Quittio::prepare()` / `PendingInvoice::prepare()`: calculation, format and profile choice and validation without rendering.
- `InvoiceBuilder::updateLine()`, `removeLine()` and `InvoiceLine::withNetPrice()`.
- Complete reference documentation: new pages Building invoices, Laravel integration and Configuration; every builder method, config key (both packages), command, event, exception, tax preset and rule is documented, the Managed layer page covers models, numbering, archive, immutability, delivery, audit log, authorisation and retention in full.
- Documentation website built from `docs/` with Jekyll and Just the Docs (navigation, search), deployed to Cloudflare by `.github/workflows/docs.yml`; the Markdown files stay the only source.
- Country pack Germany: tax preset `VatPreset::TriangularTransaction` for intra-community triangular transactions (section 25b UStG, wording of section 14a (7) UStG).
- Country pack Germany: rule `DE-USTG-11` requires the VAT identifiers of seller and buyer for reverse charge services in another member state and for triangular transactions (section 14a (1) and (7) UStG); the tax number or a legal registration identifier is not sufficient there.
- Country pack Germany: `->deductAdvance($advanceInvoice)` for final invoices (section 14 (5) sentence 2 UStG): references the paid advance invoice, adds it to BT-113 and itemises its net amounts and VAT per rate in a note. `InvoiceBuilder::addPrepaid()` adds to BT-113.
- `quittio.seller.small_business` now takes effect: `Seller::apply()` marks the invoice ( `Meta::FLAG_SMALL_BUSINESS`) and the German pack rejects VAT on it ( `DE-USTG-09`).
- Official KoSIT test for every German tax preset in XRechnung CII and UBL; the XRechnung golden-file tests run in the official CI job; CI validates every package `composer.json`.
- Laravel: `format_resolver.peppol_lookup` (invokable class or callable receiving the `BuyerParty`) for the automatic Peppol choice; `Quittio::coreWithLevels()`; `RenderedDocument::hasPdf()`; `Quittio::fake()->documents()`.
- Core: `LineBuilder::showGrossPrice()`; `InvoiceBuilder::payee()` accepts a `PayeeParty`, identifier schemes or a `PartyBuilder` callable; `Quittio::cancellation()` takes an optional `$title`; country pack readers ( `CountryPack::readers()`) are used by `read()` and `validateFile()`.
- Country pack Germany: info `DE-LEITWEG-ID-SUSPECT` for buyer references shaped like a Leitweg-ID with wrong check digits; warning `DE-USTG-13` when `newVehicle()` is used without a line of category K.
- Country pack Germany: the base rate (§ 247 BGB) can be updated without a release: `quittio-de.base_rates` in the new configuration `config/quittio-de.php`, `php artisan quittio:base-rate:update` fetching it from the statistics API of the Deutsche Bundesbank ( `BundesbankBaseRates`), or `BaseRates::register()`; `DefaultInterest` uses these rates by default. The pack has a Laravel service provider of its own ( `GermanyServiceProvider`, discovered automatically).
- Country pack Germany: tax numbers (BT-32) of German sellers are checked for format and check digit according to the ELSTER procedures of every federal state (warning `DE-TAX-NUMBER`); `TaxNumber` parses the ELSTER, federal and state notations.
- Country pack Germany: rule `DE-USTG-14` rejects intra-community supplies (category K) of small businesses except for new vehicles (section 19 (1) sentence 2 and (6) sentence 1 UStG); warning `DE-USTG-15` for invoices on intra-community supplies and on services in another member state issued after the 15th of the month following the supply (section 14a (1) sentence 2 and (3) sentence 1 UStG); `UstgRules::issuingDeadline()`.
- Documentation for AI assistants: `llms.txt`, `llms-full.txt` and every page as Markdown on the website, a read-only MCP server at `https://docs.quittio.dev/mcp` (tools `search_docs`, `get_page`, `list_pages`) and Laravel Boost guidelines and the skill `quittio-development` in `quittio/quittio` and `quittio/laravel`.
- Core: shorter invoice code. Lines can be given as name with named values ( `->line('Consulting', netPrice: '120.00', quantity: 4, unit: UnitCode::Hour)`, also `vat`, `description` and `priceInclVat`; the same in `Line::make()`, `subLine()` and the document builder), as `Line::make('Consulting', …)->…` or as arrays whose keys are the `LineBuilder` methods ( `LineBuilder::ARRAY_KEYS`, `fill()`, `Line::fromArray()`), parties as `Party::make('Kunde AG')->…` or as application models: `->buyer($customer)` for models implementing `ProvidesParty`. `subLine()` and the document builder accept the same forms.
- Core: default VAT for lines without `vat()`: `InvoiceBuilder::defaultVat()` and `DocumentBuilder::defaultVat()` per invoice, `InvoiceBuilder::useDefaultVat()` for the application, `CountryDefaultVat` (configured preset, otherwise the standard preset of the seller's country pack, for small business invoices its small business preset), `CountryDefaults::$vatPreset` and `$smallBusinessVatPreset` (Germany: `de.standard_19`, `de.small_business`), `CountryRegistry::taxPreset()`.
- Core: `InvoiceBuilder::applyDefaults()` remembers the defaults of a seller; `seller()` with another seller removes them again, except values the caller set. `Quittio::invoice()` and the document methods use it, so another seller gets neither the bank account nor the small business flag (nor, with quittio/managed, the payment terms, design, locale, time zone and currency) of the configured seller.
- `validation.locale`: the language of validation messages, independent of the invoice language. In Laravel the default is the language of the application ( `app()->getLocale()`), `'invoice'` restores the language of the invoice; without Laravel the default stays the invoice language, `'app'` uses the translator's locale. `ValidationContext::messageLocale()`.
- Laravel: `Quittio::invoice()->…->check()` validates without rendering.
- Core: fewer callbacks. `dueInDays()`, `cashDiscount()` and `lateFee()` on the invoice and document builder replace `paymentTerms(fn ($t) => …)`; `presentation()` takes an array of changes; `updateLine('2', netPrice: '80.00', quantity: 3)` takes named values; `payee()` takes a `PartyBuilder`. The callbacks keep working.
- Laravel: `QUITTIO_SELLER_SMALL_BUSINESS` for `quittio.seller.small_business`.
- Laravel: `config/quittio.php` explains every key; `pdf.colors.secondary` is listed (default `null`, as before).
- PDF: carry-over across pages. When the line table continues on the next page, the page ends with "Fortsetzung auf Seite 2 · Übertrag" and the sum of the lines so far, the next page starts with "Übertrag von Seite 1" (English "Continued on page 2 · Carried forward", "Brought forward from page 1"). The mPDF renderer lays a document out again only when the lines span pages; own templates enable it with markers ([templates](https://github.com/Quittio/quittio/blob/master/docs/templates.md#carry-over-across-pages)), view model `lineGroups[].lines[].carryOver`. Following pages get a header with logo or name, title and number, recipient, customer number and date.
- Fonts: Geist (SIL Open Font License) is bundled and the default font, with the family `geistmedium` (Medium, SemiBold) for medium weights; Inter stays bundled ( `pdf.font = 'inter'`, also for Greek).
- View model: `design.fontMedium`, `design.continuationMarginTop`, `design.logoMaxHeight`, `design.footerHasTaxIds`, `totals.dueEqualsGross`; labels `payment`, `transfer_until`, `remittance_short`, `vat_row_single`, `your_vat_id`, `your_tax_number`, `tax_number_short`, `carry_over`, `carry_over_from`, `continued_on`.
- Documentation for first-time users: new pages E-invoicing basics (EN 16931, CII and UBL, formats, profiles, rule codes, which format you need, German terms) and Troubleshooting (common errors with cause and fix); Getting started shows the minimal configuration of your company and explains a first invoice line by line; every page starts with what it is for, explains its terms and is ordered from the common case to the reference; German text in the English documentation is translated or explained.
- Laravel: `quittio.defaults.vat` (tax preset of lines without `->vat()`, default the standard rate of the seller's country) and `RenderedInvoice::cancel($number, reason: …)`, which renders the cancellation in the formats of the invoice; `Quittio::defaultVat()`.
- Laravel: `Quittio::invoice()` starts an invoice with the seller, bank account and small business setting of the configuration and renders it with `->render()` (optionally a format or a list of formats); `Quittio::quote()`, `orderConfirmation()`, `deliveryNote()`, `proforma()`, `paymentReminder()` and `accountStatement()` start documents the same way. The seller comes from the binding of `Quittio\Laravel\Contracts\InvoiceDefaults` (default `ConfigInvoiceDefaults`; quittio/managed binds the current issuer).
- Documentation page Examples: complete examples from service invoices, small businesses, XRechnung and customers abroad to cancellations, Laravel orders, drafts, reminders and incoming invoices; a test runs the code of the page, and another one checks that every code block of the documentation imports the classes it uses.

### Changed

- Country pack Germany: `DE-USTG-01` names the party and the missing address fields ("Die Anschrift des leistenden Unternehmers (Verkäufer, BG-5) ist unvollständig, es fehlt: Straße und Hausnummer, Postleitzahl, Ort") and says where to fill them in. The message of `ValidationException` contains the hint of every listed finding.
- Core: macros of `InvoiceBuilder`, `LineBuilder` and `DocumentBuilder` run in the scope of the builder class, so they reach its state also on subclasses.
- Core: a line without `quantity()` has the quantity 1 instead of failing with BT-129.
- Repository layout: the root package is `quittio/quittio` (it replaces `quittio/core`, `quittio/laravel` and `quittio/country-de`); the meta package was removed; the packages are split into read-only repositories on every push; the commercial `quittio/managed` lives in its own repository.
- Country pack Germany: the format rule only decides for public buyers (Leitweg-ID with valid check digits or endpoint 0204: XRechnung, also for sellers abroad) and domestic small amount invoices (PDF); consumers, the Peppol lookup, domestic B2B (ZUGFeRD with the configured profile), sellers outside Germany and buyers in Büsingen or Heligoland are left to the format resolver.
- `check()` and `prepare()` always validate (whatever `validation.mode` or `withoutValidation()` say), validate the CII XML that `pdf` embeds with `b2c_embed_xml` exactly as `render()` writes it, and refuse XML formats for watermarked data like `render()`.
- Laravel: `InvoiceValidated` is no longer dispatched in validation mode `off`; the unused `networks` config section was removed; `Quittio::fake()` picks format and profile like a real run ( `defaults.format`, automatic choice, profile keys, all formats with `as()`), honours `htmlOnly()` and throws for unknown formats or profiles.
- English tax and legal texts of the German pack use the terms of Directive 2006/112/EC; `LegalTexts` notices take the preset texts, so one notice has one wording.
- Font directories configured for the mPDF renderer take precedence over the bundled fonts and the mPDF fonts; fonts published with `--tag=quittio-fonts` are found without configuration.
- New design of the default templates (Blade and plain PHP): logo or issuer name at the top left; the sender line at the top of the address field and the recipient directly below it (the DIN 5008 zones stay available to own templates); the invoice details on the right; the line table with a rule below the column heads, item names in medium weight, a VAT column only for several rates; totals with "USt. 19 %" for a single rate and the gross total (or the amount due) large in the primary colour; payment terms, bank details and payment QR code side by side; a footer in four columns (address; phone and e-mail; register and legal information; VAT identifier and tax number, which leave the invoice details) with the page number centred. New default colours `#2741d9`, `#15171c` and `#5f6470`, top margin of the first page 15 mm, fold and punch marks on by default ( `pdf.fold_marks`), the bank details are no longer repeated in the footer, the account holder is printed only when it is not the issuer. German labels: "Beschreibung", "Betrag", "Zahlung", "GiroCode", "2 % Skonto bis 10.10.2026: 2.692,76 €", "Bitte bis zum 17.10.2026 überweisen." for credit transfers, "Ihre USt-IdNr."; service periods within one year read "01.10.–31.10.2026".

### Fixed

- Laravel: a published `config/quittio.php` without `validation.levels` keeps the default checks ( `php`, `xsd`) instead of running none; only an empty list switches them off.
- The hint of rule `BR-CO-25` names `->dueInDays(14)` instead of the callback form; a validation message with one finding reads "(1 error)".
- Documentation: facts corrected against the code, among them the order in which the profile is chosen, the `template` of a presentation passed to `->presentation()`, the signatures of `line()`, `subLine()` and the document line methods, the day count in the default interest examples, `BundesbankBaseRates::fetch()` (an instance method), the check of German tax numbers ( `DE-TAX-NUMBER`) and that an unavailable veraPDF stops the rendering by default.
- Amounts in locales with a multibyte grouping separator (French) were garbled: the digits were grouped by reversing the string bytes including the separator. ICU's narrow no-break space is now replaced by a no-break space, which every bundled font has.
- Legal references: self-billed invoices are section 14 (2) sentence 5 UStG (was sentence 2); `DE-USTG-10` names its basis (Article 230 VAT Directive, section 16 (6) UStG).
- `quittio:validate --kosit/--verapdf` uses every driver setting ( `java`, `docker`, `timeout`, `fail_on_unavailable`) and no longer changes the cached core; `defaults.format = 'auto'` is accepted in Laravel and as issuer default; `quittio:preview` and the preview route accept the views of `pdf.templates`; the facade docblock lists every manager and fake method; the ASCII fallback file name of downloads transliterates characters ("Ü" becomes "U").
- Profile validation no longer warns about postal addresses in BASIC WL and BASIC; address fields carry their Factur-X levels and the business terms of their context (e.g. BT-55 for the buyer country). Data of EXTENDED and of the XRechnung extension, and fields below a field that is not allowed, are reported once.
- Reading a CII or UBL invoice without document totals reports BR-12 to BR-15 instead of `QUITTIO-NOT-CALCULATED`.
- In the view model of documents (quotes, reminders …) `document.typeCode` is `null` and `document.type` names the document type; the default templates highlight lines marked with `highlight()` and use `colors.secondary`; `CountryDefaults::$paymentQr` selects the QR code of the mode `auto`; self-billed invoices take their title from the country pack's correction policy.
- `paymentTerms()` with a callable continues existing terms, also after `InvoiceBuilder::from()`.
- Country pack Germany: `DE-USTG-06` accepts the pack's reverse charge texts in every shipped language; `newVehicle()` adds the note of section 14a (4) UStG; `deductAdvance()` writes the whole note in one language and rejects documents that cannot be advance invoices (credit notes, corrections, negative totals); `VatPreset::exempt()` defaults to German like the enum presets; `DefaultInterest` uses the day count of the dunning law (365) and `BaseRateTable::periods()` merges periods with the same rate.
- Floats as amounts, prices, rates and quantities are rejected with an `InvalidArgumentException` also in files without `declare(strict_types=1)`; before, PHP turned `netPrice(19.99)` into `19` for parameters typed `BigDecimal|int|string`. The same applies to `InvoiceLine::withNetPrice()`/ `withPriceInclVat()`, `CustomTaxPreset::make()` and partial cancellations of the Managed layer.
- UBL credit notes write the tender or lot reference (BT-17) as `OriginatorDocumentReference` in the element order of `CreditNote`; it was dropped before.
- Default line identifiers skip identifiers set with `id()` (a line without `id()` and one with `id('1')` both got `1`); identifiers used twice make `build()` throw `InvalidInvoiceData`, and data from other sources gets the warning `QUITTIO-LINE-ID-DUPLICATE`.
- The configured profile ( `defaults.profile`) applies to every format that allows it, also to `->format('zugferd')` and formats chosen by a country rule; `Config::$profile` defaults to `null` (format or automatic choice decides). XRechnung CII with sub lines reports the sub lines in the validation instead of failing with "does not support profile extended".
- The `template` of the presentation passed to `->presentation()` and of the configured presentation selects the template (after `->template()` and the invoice's own presentation).
- Laravel: country packs listed in `quittio.countries` replace discovered packs with the same code (e.g. a subclass of `CountryDE`).
- `swiss-qr-bill` without a generator fails with a `ConfigurationException` instead of printing no code; generators are registered with `Quittio::withPaymentQrGenerator()` or `quittio.pdf.payment_qr.generator`. PDF renderers whose `supportsEmbedding()` is `false` get PDF/A and the embedded XML from `MpdfPostProcessor`; `CallbackRenderer` and `PassthroughRenderer` report `true`.
- A missing `java`, `verapdf` or `docker` binary is reported as `KOSIT-UNAVAILABLE`/ `VERAPDF-UNAVAILABLE` instead of aborting the render run with an `ErrorException` in Laravel.
- Country pack Germany: invoices with `VatPreset::ZeroRatedPv` (section 12 (3) UStG) failed BR-Z-10, because the preset sent an exemption reason; the zero rate is now stated as the rate only.
- Country pack Germany: order numbers shaped like a Leitweg-ID (e.g. `4711-01`) no longer switch the format to XRechnung; only a Leitweg-ID with valid check digits or a `0204` endpoint does, and the check digit warning is limited to public buyers.
- Country pack Germany: "Gutschrift" is required for all self-billed type codes (261, 389, 527), not only 389.
- Country pack Germany: default interest texts named the first day of the next period as end date; they now name the last day with interest.
- Country pack Germany: the small amount simplifications (section 33 UStDV) no longer apply to reverse charge, intra-community supplies and distance sales (section 33 sentence 3 UStDV, rule `DE-USTG-12`); such invoices need all mandatory information and are not rendered as plain PDF.
- Country pack Germany: `DE-USTG-09` also rejects VAT on document level charges of small businesses; `DE-USTG-01` requires the postcode of German buyers; `DE-USTG-11` also applies to reverse charge lines without a preset when the buyer is in another member state.
- Country pack Germany: `->deductAdvance()` rejects advance invoices in another currency and deducts the amount received (including a cash rounding BT-114).
- Country pack Germany: the base rate table rejects dates from the next scheduled change (1 January or 1 July) after the last known rate instead of silently using the old rate ( `BaseRateTable::validUntil()`); the § 288 (5) BGB flat rate uses the money context of the documents.
- `quittio.storage.disk` is used as the default disk of `save()`.
- Package dependencies: `quittio/core` requires `ext-gd` (needed by mPDF) and `ext-ctype`, `quittio/country-de` declares Brick, `quittio/laravel` and `quittio/managed` require `laravel/framework` (they use Illuminate\\Foundation); the autoload prefix of `quittio/laravel` is `Quittio\Laravel\`.
- Calculation: exemption reasons are only written into VAT breakdowns of categories that allow them (E, AE, K, G, O); S and Z breakdowns no longer fail BR-S-10/BR-Z-10.
- Calculation: gross prices and document allowances are distributed with signed weights, so vouchers, returns and negative lines keep their sign and correct net amounts; a negative gross price is rejected.
- Calculation: document allowances and charges accept an exemption reason and code for VAT groups they create alone; sub lines with a VAT category or rate other than their parent are rejected ( `QUITTIO-SUBLINE-VAT`).
- XML: BT-6 is omitted when it equals the invoice currency (BR-53 in CII); MINIMUM writes only the seller country; a warning reports preceding invoices (BG-3) that CII cannot carry ( `QUITTIO-PRECEDING-INVOICES-CII`); XRechnung BT-20 contains free text, due days and late fee terms before the `#SKONTO#` lines.
- Reading: exemption reasons of the VAT breakdown are copied to the lines, a declared BT-111 survives recalculation, all VATEX codes of the code list are accepted.
- PDF: watermarked drafts and previews never embed e-invoice XML (an embedded format with a watermark throws), watermarked documents and HTML show the watermark.
- PDF: the mandatory field guard only counts printed values (not `count()` or loops) and checks regulatory notes in `legalNotes`; the German pack uses the keys `servicePeriod`, line periods and `taxRepresentative.vatId`.
- PDF: the seller's tax representative (BG-11), payee (BG-10), delivery address (BG-13) and price base quantity (BT-149) are printed; every cash discount tier shows its own amount; credit notes show "Erstattungsbetrag" without bank details; titles follow the type code family (self-billed → "Gutschrift", credit notes → "Rechnungskorrektur", 325 → "Proforma-Rechnung", 386 → "Anzahlungsrechnung"); commercial credit notes are no longer labelled "Gutschrift" in the code lists.
- PDF: the DIN 5008 address field keeps its position with a logo; VAT rows are labelled per category; split allowances name their VAT rate; quotes and order confirmations show no payment block or GiroCode; the EPC payload respects the 331 byte limit; the render locale wins over the invoice locale.
- Security: template names from requests or options are never file paths ( `PhpTemplateEngine` resolves names only inside the configured template directories); the preview route accepts only the default, the configured and the package templates.
- PDF/A: logos are re-encoded as RGB PNG on white (logos with transparency or above 600×200 px made every ZUGFeRD render fail), SVG logos are rasterised (Imagick) or rejected; the GiroCode PNG is compressed.
- PDF: the mandatory field guard checks every line (name, quantity), every VAT row, every legal note, the cash discount terms, both buyer name and address, the service date (BT-72/BG-14, otherwise every line period) and the full tax representative; null values no longer count as printed.
- PDF: self-billed invoices show the buyer as issuer and the seller as recipient, with payout wording and without GiroCode; margin scheme and travel agency rows state no VAT amount (section 14a (6) UStG); descriptions and notes are plain text by default (Markdown opt-in, it may change the displayed text); a watermark together with any XML format throws; per-call presentations merge over the configured one; payment reminders encode the total and the open invoice numbers in the GiroCode; DIN 5008: the recipient starts in the Anschriftzone.
- XMP: `fx:Version` is the XRechnung version for the XRECHNUNG conformance level, the XRechnung extension declares `XRECHNUNG`.
- XML (EXTENDED): exemption reasons on line and allowance/charge level, one payment terms group per cash discount tier, the exchange rate; German BT-20 free text uses German number and date formats.
- Builder: `payment()` replaces the payment instructions instead of accumulating accounts (duplicate IBAN and lost BT-83 in foreign currency invoices, BR-DE-25-b on direct debit); percentage allowances and charges follow their base after line changes; `InvoiceLine::withPriceInclVat()`, price modes cannot be mixed.
- Cancellations: read foreign currency invoices keep BT-111 (implied exchange rate), XRechnung third-party payments are reversed in full cancellations only, gross-price lines can be cancelled by amount, self-billed documents stay self-billed (389 ↔ 261).
- Laravel: `seller.identifiers` (BT-29) for sellers without VAT identifier; explicit `pdf.paper` wins over the country default; unknown letter layouts and QR types throw; queued renders travel as snapshots through the upcaster chain; removed the unused `defaults.currency`, `defaults.timezone` and `defaults.standard`.
- Reading: own PDF parser with cross-reference streams, object streams and incremental updates (PDFs from PDFBox, iText, Acrobat or Word could not be read); name tree loops, exponent numbers, oversized tags and attribute floods are rejected; strict dates (never replaced by today, BR-03 for a missing issue date); no default currency (BR-05), BT-110 only in the invoice currency, BT-149 from the gross price, BR-CL-06 for BT-8, BR-DEC as errors, sanitised attachment names, embedded files chosen via /AF with findings for ambiguous PDFs, a specific message for ZUGFeRD 1.0; MINIMUM and BASIC WL documents without lines no longer trigger line based rules.
- Reading API: `read()` and `validateFile()` take the content only, never a path; `readFile()` and `validatePath()` read files.
- Documents: proforma invoices (325) are rejected in the invoice pipeline ( `QUITTIO-PROFORMA`, use `DocumentBuilder::proforma()`); payment reminders and account statements take no lines, the reminder total is open items + fees + interest without VAT and the GiroCode uses it with the open invoice numbers; account statements respect their period; interest uses actual/actual per calendar year and the text names the last interest day; level 1 reminders are titled "1. Mahnung".
- Countries: the buyer's country pack also applies for sellers outside the EU (e.g. XRechnung for German public buyers); `VatTerritory` knows the EU VAT territory (XI for goods, Monaco, Isle of Man, Büsingen, Helgoland and other excluded areas); VIES is only queried for EU member states and XI, and unavailable answers are not treated as invalid; L7 warnings for intra-community supplies and exports to the wrong destination.
- Partial cancellations reverse taxable amounts and VAT exactly: per VAT group the VAT of a cancellation is round2(cumulative cancelled taxable amount × rate) minus the VAT already cancelled, the closing cancellation takes the original's VAT; in gross price mode the net amounts are aligned the same way (cumulative gross / (1 + rate)), so BT-116 and BT-117 per group and BT-109 to BT-115 add up exactly over every sequence; each document stays within one cent of its own rounding and keeps the sign of its taxable amount (BR-CO-17); the same for BT-111 in foreign currency invoices; originals of other systems with their own rounding are aligned with their effective rate. Managed stores the cancelled amounts per group ( `vat` on invoice relations), recomputes them under lock and refuses a cancellation that raced with another one; core users can pass a `CancellationHistory`, which is validated against the original. Aligned documents carry the info `QUITTIO-CANCELLATION-VAT-ALIGNED` and a note sentence when a group's VAT differs from its own rounding; drafts keep a declared VAT breakdown only for aligned cancellations.
- Reading PDFs: the reconstruction of damaged files scans one object at a time and stops above 100,000 objects, PNG predictors only process the data present, the catalogue search no longer caches every object (memory and CPU exhaustion with small crafted files).
- PDF: invoices with line groups ( `->group()`) failed to render under Laravel (mPDF warning with `packTableData`); refunds and self-billed invoices no longer announce a direct debit; SVG logos are read only with the SVG coder at a bounded resolution, logos above 10 MB or 25 megapixels are rejected; the GiroCode beneficiary falls back to the seller name; partials cannot be previewed as templates.
- Reading XML: encodings that hide the markup from the pre-scan (UTF-7, EBCDIC, UTF-32) and DOCTYPEs are rejected before libxml parses them, namespace declarations in scope are limited (CPU exhaustion with libxml < 2.12); BT-6 is no longer interpolated into XPath (injection of BT-111); relative date strings ("tomorrow 2026", "+2000 days") are rejected also in the builder; cash discount periods in weeks; bidi control characters are stripped from attachment names.
- Calculation: different exemption reasons in one VAT group are joined in BT-120 (e.g. § 4 Nr. 14 UStG together with a margin scheme), BT-121 is only kept when the codes agree ( `QUITTIO-EXEMPTION-CONFLICT` warning); percentage document allowances follow removed lines; line ids no longer collide after `removeLine()` and `line()`.
- Cancellations of self-billed invoices are titled "Storno-Gutschrift" with the note "Stornierung der Gutschrift …" ( `CorrectionPolicy::cancellationTitle()`, title key `cancellation_self_billed`).
- Country pack Germany: the § 3c distance sale exclusion of small amount invoices uses the VAT territory and the deliver-to address and only warns; "Gutschrift" may be given in another official EU language (UStAE 14.5 Abs. 24); small amount invoices in a foreign currency are compared by their EUR equivalent.
- PDF: remote logos are fetched by Quittio only from public addresses (checked per resolved IP and redirect, connected to the checked IP), mPDF never fetches URLs; Blade templates are restricted to an allowlist ( `quittio.pdf.templates`, default `invoices.*`); the guard requires the unit and the seller's legal name; refunds of negative invoices are shown as positive amounts; `Presentation::$explicit` allows per-invoice resets.
- Cancellations and unchanged `InvoiceBuilder::from()` keep the declared line and VAT amounts of read invoices within the EN 16931 rounding tolerance, so foreign invoices using other rounding are reversed exactly ( `QUITTIO-DECLARED-AMOUNTS` warns when amounts had to be recalculated); an exchange rate implied from BT-111 is dropped once amounts change; amount discounts split across VAT rates are re-split after line changes; third-party payments (BG-DEX-09) are rejected where the syntax cannot carry them ( `QUITTIO-THIRD-PARTY-PAYMENTS`).
- Validation knows the XML syntax that is written, so syntax specific rules apply (e.g. BR-DEX-15 for XRechnung CII); UBL writes BT-82 and the credit note due date only once with several accounts (UBL-SR-45/46).
- PDF: mPDF cannot fetch anything over HTTP (deny-all client), logo values are strictly classified (no backslashes, protocol-relative URLs or surrounding whitespace; data URIs strictly decoded and re-encoded; SVG entity declarations refused in every mode); IPv6 site-local addresses are refused for remote logos.
- Declared amounts: only set when the recalculation does not reproduce them, line net amounts kept only within 0.02 of the unrounded formula ( `QUITTIO-LINE-ROUNDING`), and only while a fingerprint of the amount inputs matches (also for read data edited before `from()`), so edits outside the builder never keep stale amounts; categories without VAT never keep a declared VAT amount; PEPPOL-EN16931-R120 uses the official tolerance of 0.02.
- Country pack Germany: `DE-XRECHNUNG-EXT-01` rejects credit notes of the XRechnung extension in UBL (no validator scenario; use the negative\_invoice strategy).
- `pdf.paper` and the VIES verification ( `validation.drivers.vies.enabled`) take effect; file names of XML-only formats no longer contain a raw translation key.
- Watermarks (draft and preview PDFs) were never printed: mPDF needs `showWatermarkText`, and PDF/A forbids their transparency. Watermarked PDFs without embedded XML are now rendered without PDF/A.

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://quittio.dev/en#website","@type":"WebSite","description":"E-invoicing for PHP and Laravel: create, validate, read and archive ZUGFeRD, XRechnung and Peppol invoices.","inLanguage":"en","name":"Quittio","url":"https://quittio.dev/en","publisher":{"@id":"https://quittio.dev/#identity"},"translationOfWork":{"@id":"https://quittio.dev/#website"}},{"@id":"https://quittio.dev/en/changelog#webpage","@type":"WebPage","description":"What’s new in Quittio, version by version, straight from CHANGELOG.md on GitHub.","name":"Changelog","url":"https://quittio.dev/en/changelog","breadcrumb":{"@id":"https://quittio.dev/en/changelog#breadcrumb"},"isPartOf":{"@id":"https://quittio.dev/en#website"},"potentialAction":[{"@type":"ReadAction","target":["https://quittio.dev/en/changelog"]}],"primaryImageOfPage":{"@id":"https://quittio.dev/#logo"}},{"@id":"https://quittio.dev/#identity","@type":"Organization","description":"Open-Source-Bibliothek für E-Rechnungen in PHP und Laravel (ZUGFeRD, XRechnung, Peppol) und Quittio Managed.","email":"kontakt@niklasforst.de","legalName":"Niklas Forst – Softwareentwicklung","name":"Quittio","url":"https://quittio.dev","founder":{"@type":"Person","name":"Niklas Forst","url":"https://quittio.dev/ueber"},"logo":{"@id":"https://quittio.dev/#logo"},"sameAs":["https://github.com/Quittio/quittio","https://packagist.org/packages/quittio/quittio"]},{"@id":"https://quittio.dev/en/changelog#breadcrumb","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","name":"Home","item":"https://quittio.dev/en","position":1},{"@type":"ListItem","name":"Changelog","position":2}]},{"@id":"https://quittio.dev/#logo","@type":"ImageObject","caption":"Quittio","contentUrl":"https://quittio.dev/logo.png","inLanguage":"en","url":"https://quittio.dev/logo.png"}]}
```