3 min readOct 20, 2026by jakub

Document Numbering

Give every order, invoice, shipment and credit memo a number your accountant will accept: in the pattern your market expects, never issued twice, and with a recorded reason behind every gap. Nothing changes when you install it, so you can move one document type at a time.

Latest version: 1.0.0 — changelog

The Numbering Series grid, with the next number a series would issue highlighted

Who it's for

  • Stores whose invoices must run in unbroken sequences, per year or per month. Strict allocation is gapless, and the reset policy restarts the counter on schedule.
  • Stores selling into several countries or currencies that must number each one separately. A counter scope such as {yyyy}/{mm}/{billingCountry} gives every country its own sequence each month.
  • Stores with years of existing documents that want the new numbering applied to that history, oldest document first.
  • Finance teams and auditors who have to account for every number, including the ones that were never used.

Why it matters

  • Numbers that match how you file. Compose them from the date, store, website, billing country, currency, customer group, document type and a padded counter, instead of accepting Magento's single fixed sequence.
  • No number is ever issued twice. Every number is claimed atomically, so two checkouts finishing at the same moment cannot receive the same one — and a number already on a document is refused rather than issued a second time.
  • Every gap has an explanation. The numbering register records each number drawn, reserved, converted, expired, refused or changed. qoliber:number:audit exits non-zero on a number nothing explains, so a gap raises an alarm in cron or CI instead of surfacing during an audit.
  • Corrections that stay defensible. An authorized admin changes an assigned number with a mandatory reason; the old number is retired for good and the change is recorded against their user.
  • Safe to install. With no series configured, Magento numbers every document exactly as it did before.

See it in action

Invoice numbers that restart every month. You set the format FV/{yyyy}/{mm}/{counter:5} and a monthly reset → you get invoices such as FV/2026/01/00042, and February's first invoice starts again from the series' first number.

Each country numbered on its own. You set the counter scope {yyyy}/{mm}/{billingCountry} and the format FV/{yyyy}/{mm}/{billingCountry}/{counter:5} → in January your Polish invoices run FV/2026/01/PL/00001, FV/2026/01/PL/00002, while the first German invoice is FV/2026/01/DE/00001.

Credit memos that quote their invoice. You give a credit memo series the format KOR/{invoiceNumber}/{counter:4} → its first credit memo, raised against invoice FV/2026/01/00042, is numbered KOR/FV/2026/01/00042/0001.

Features

FeatureBenefit
Set up numbering seriesDefine a numbering scheme per document type, preview the next number before anything is issued, and restrict each series to the stores, websites, customer groups, countries or currencies it belongs to.
Read the numbering registerAnswer "what happened to this number?" from a read-only, append-only record — including numbers that never reached a document.
Change an assigned numberCorrect a wrong number without touching the database, with the reason and the admin on record and the old number retired for good.
Command line and cronAudit, correct counters, write off abandoned reservations and renumber years of history from the command line or from cron.
Format variables and padded countersPrint the number the way your accountant files it, without custom code.
Counter scope and reset policiesKeep separate, contiguous sequences per country, month or store, restarting daily, monthly or yearly.
Strict and fast allocationChoose gapless numbering, or higher throughput with every gap still accounted for.
Order allocation: reserve at checkout or allocate on savePass the final order number to your payment gateway, or keep order numbers gapless — chosen per series.
Two-level permissionsLet staff correct documents nobody has seen yet, while sent documents need a stronger permission.
REST API for seriesManage numbering configuration from your own tooling or deployment pipeline.

The Numbering Register, a read-only record of every numbering event

Competing solutions

The right-hand column describes common market practice, not any particular vendor.

QoliberTypical marketplace extension
GitLab accessFull access to the module's GitLab repository — source, history, issues and merge requestsVaries by vendor
Packagist installationInstalled and updated with Composer from our private Packagist (qoliber.repo.packagist.com)Varies by vendor
Slack access to the development teamA shared Slack channel with the developers who build and maintain the moduleUsually ticket-based
Unit tests307 PHPUnit unit tests (45 classes) in the repositoryNot typically published
Integration tests191 Magento integration tests (55 classes), run before every releaseNot typically published
E2E Playwright tests30 Playwright end-to-end tests (7 spec files) against the Magento admin and the REST API, run before every releaseNot typically published
DocumentationFull docs portal: install, configuration, usage, troubleshooting, developer guide and API referenceVaries by vendor
PHP / Magento rangePHP 8.1 to 8.5; magento/framework ^103.0 with magento/module-sales ^103.0 or ^104.0Varies by vendor

What sets it apart

  • API-first. Every series operation is available over REST, and the service describes itself over SOAP and in Magento's REST schema.
  • Runs inside your store. Counters, claims and the register live in your own database; numbering never calls an outside service.

Good to know

  • Configured per series, not under Stores > Configuration. Each document type needs its own series, and a document no series matches keeps Magento's own numbering.
  • Not every mode is gapless. Fast allocation and reserving order numbers at checkout each trade a gapless run for something else: a failed save or an abandoned checkout uses up a number. Strict allocation, with order numbers allocated on save, is gapless — and in every mode the register and the audit explain each gap.
  • The register is never pruned. It is the evidence behind every number, so it grows for the life of the store; a retention policy is your decision.
  • A number is at most 50 characters long.

Supported versions

PHP 8.1, 8.2, 8.3, 8.4 and 8.5. Magento Open Source and Mage-OS on magento/framework ^103.0 with magento/module-sales ^103.0 or ^104.0. Tested on Mage-OS 3.3.

Next steps