CoeveraBlueprints

Blueprint 006 · Numbering

How do you set up document numbering that survives production?

Invoice numbers, case references, document numbers. Getting one generated is a five-minute job. Making sure it is still correct in eighteen months, after somebody has edited the pattern, is the actual problem.

Revised 2026-09-07Verified against a live Coevera spaceMarkdown twin ↓

The short answer

Use an Auto number field. Its pattern is a builder of segments — literal text, a Year (YYYY) token, an Autocount — and the Autocount segment carries a radio for "Reset count every year" against "Don't reset count". Annual reset is native. No automation required.

If you later change the pattern, leave the trailing number out. The ,1 in {#Number4,1} is a start index, not decoration: it says begin this series at 1, and it does exactly that whenever it is sent — including on a field that has been issuing numbers for two years. Write {#Number4} and the count carries on from where it was.

01The business problem

A business document needs a human-facing reference — an invoice number, a case number, a document number that appears on paperwork and gets quoted in emails and phone calls. The requirements are unglamorous and strict:

  • Unique, permanently. Two documents sharing a number is not a cosmetic problem.
  • Readable and speakable — a person reads it aloud down a phone line.
  • Year-scoped, in most jurisdictions and most accounting practice: the sequence restarts each January so the number carries its own period.
  • Stable — once issued, it never changes, because it is printed on documents that have left the building.

In accounting contexts this is not merely convention. A document-number series that repeats a value is an audit finding, and in several jurisdictions a compliance problem rather than an inconvenience.

02Why the obvious approach fails

Building the number yourself, because you were told you had to

You will find advice telling you to build the number yourself. It states that sequence fields cannot reset per year, and that a year-prefixed document number therefore has to be composed in an automation process — a plain counter for the running number, and a process concatenating the year onto it.

That advice is wrong, and it is repeated widely enough to be worth naming. The platform has an explicit "Reset count every year" option built into the pattern editor. Before building a composition process, open the field editor and look.

It is worth being concrete about what the unnecessary workaround costs, because the same reasoning applies whenever you replace a native mechanism with automation:

  • A second source of truth. The real counter and the composed text field can disagree, and nothing reconciles them.
  • A race. Two records created in the same instant can be composed with the same number, because the composition is not the thing enforcing uniqueness.
  • A failure mode with no signal. If the process is disabled, fails, or is filtered out, records are created with an empty document number and nobody notices until someone looks.
  • Ongoing maintenance of logic the platform would have maintained for you.

Using the record identifier

Technically unique, and useless. It is a UUID: not readable, not speakable, not year-scoped, and it tells a customer nothing.

03The pattern builder

The field type is called Auto number in the interface. Its pattern is assembled from ordered segments rather than typed as a string:

SegmentPurpose
TextA literal prefix or separator — a document-type code, a company initial.
Year (YYYY)The four-digit year, resolved when the record is created.
AutocountThe running number, with its digit width. This segment carries the reset choice.
TextFurther literal segments, before or after any of the above.

On the Autocount segment sit two mutually exclusive options: Reset count every year and Don't reset count. That single radio is the answer to the question this blueprint is named after.

The editor shows a live example of the next value as you build — Example: TST20260004 — which is useful while configuring. Treat it as a formatting check, not as evidence about the counter; only a created record tells you that.

04Configuration and the API shape

Creating one programmatically

The pattern is expressed as a token string, and the field carries a sequence object:

sequence: {
  defaultItem: { pattern: "TST{#Year}{#Number4,1}" },
  items: []
}

First record out of that pattern: TST20260001.

The create form and the read form differ. The ,1 is the start index — "begin this series at 1" — and it is normalised away once the field is published, so reading the field back returns the cleaned {#Number4}.

This is the rule for changing a pattern later: send it without the trailing number. The start index is an instruction, and it is obeyed every time it arrives. Change TST{#Year}{#Number4,1} to INV{#Year}{#Number4,1} — a prefix edit, apparently harmless — and the series restarts at 1, re-issuing numbers it has already given out. Change it to INV{#Year}{#Number4} and the counter carries on untouched.

The safe procedure, and the reason the two forms differ: read the field, take its pattern verbatim, change only what you meant to change, and send that back. What the field reports is already normalised, so it never carries a start index. If you generate payloads from a stored template rather than from a read, strip ,<n> from the count token for anything that is not a brand-new field.

Two API traps on creation. A sequence_pattern property on the REST field endpoint is deprecated — the API rejects it with a message telling you to use the sequence property instead. But posting the new sequence object over the same REST endpoint returns a 500. Creating the field through the administrative API worked; the REST path did not.

The counter is a three-part state

The field exposes its counter as last_particle, which is not a single integer:

last_particle: { year: 2026, month: 0, sequence_number: 2 }

Two things follow. The month component stays at zero when the pattern contains no month token, so its presence does not imply monthly behaviour. And the year component is the mechanism behind the annual reset — the engine holds the year the count belongs to, which is what lets it recognise a new year and start again.

Segmented counters

The items array alongside defaultItem takes entries that each carry their own pattern and their own filter. That is the shape of a mechanism for several independent counters on one field, selected by a condition on the record — a separate series per document type or per organisational unit.

Its semantics are unverified — see §6.

05When you still need automation

Mostly you do not, which is the point of §2. There is one real case where the native field cannot do the job.

The Year token resolves from record creation. If your document number's year must come from a different date — an invoice date, a document date, a service period that may fall in a different year from when the record was keyed in — the Auto number field cannot express it. The counter also advances on creation order, not on that date's order.

There, and only there, the composition approach is correct: a native Auto number supplying the guaranteed-unique running portion, and a process assembling the visible document number from the chosen date's year plus that number. Accept explicitly that creation order and document-date order can then diverge, and decide in advance which one the business considers authoritative — that question is much easier to answer before go-live than after.

06Limits & trade-offs

Gapless numbering is not achievable

A number is issued when the record is created. Create a record and delete it and the number is spent — the series carries a gap, and no configuration prevents it. If your jurisdiction or auditor requires an unbroken series, raise it before go-live, because the answer will be a reconciliation procedure rather than a setting.

The year comes from the creation date, and only from there

The Year token resolves when the record is created, and the count advances in creation order. A number whose year must come from a different date — an invoice date, a document date, a service period — cannot be expressed by the field, and §5 covers the composition you need instead. The consequence to decide up front is that creation order and document-date order can then disagree.

Several counters on one field is unverified

The items array described in §4 has the shape of a mechanism for independent series on one field. We have not tested it, and say so rather than describe behaviour we have not observed. Treat a per-type or per-unit series as a design risk until you have watched it work.

Other things to know

  • The publish operation's reported count is not a success signal. It returned zero on every call in our testing while demonstrably publishing.
  • Field creation is inconsistently published. The identical creation call returned an already-published field once and an unpublished draft another time. Check the published state; do not assume it.

07Verification

Numbering is one of those features that looks correct until it is audited, so the checks are about issued values rather than configuration.

  • Read numbers from created records, not from the field configuration. The configuration tells you what the engine intends; only an issued number tells you what it did.
  • Create at least three records and confirm the increment, rather than one and assuming.
  • Read the counter back after any configuration change — the year and count components should match the last number issued. Read the pattern back at the same time: that is the string you must reuse for the next edit.
  • After any pattern edit, publish, then create one record and check its number against the highest already issued. It takes seconds and it is the check that catches a counter that did not carry over.
  • Test uniqueness as a query, not as an assumption: group by the number field and confirm no value appears twice. Do this after every configuration change, and once as a scheduled check if the numbers matter for audit.
  • If annual reset is enabled, verify it against a real year boundary before relying on it. We could not, and say so rather than assert behaviour we have not watched happen.

What would signal a regression: any duplicate value in the number field; a counter whose year component disagrees with the numbers being issued; a record created with an empty number, which means a composition process failed rather than the native field.

Published by Coevera · abstracted to the pattern, no client dataBlueprint 006 · rev 2026-09-07