Skip to content

Filing Rules

Every document you add to Papermerge needs a home — a folder where it will be stored. Deciding that folder each time is surprisingly tedious: the larger your document base grows and the more complex your folder layout becomes, the harder it is to remember where each type of document should go.

Filing rules solve this by letting you define the destination once, per document type. From then on, Papermerge moves documents of that type to the right folder automatically.

Consider a concrete example: you receive an invoice from a supplier named Acme GmbH. You open Papermerge to file it. Where does it go?

  • /home/Suppliers/2024/acme-gmbh/invoice-2024-01.pdf?
  • /home/Invoices/2024/Suppliers/acme-gmbh-2024-01.pdf?
  • /home/Accounting/Invoices/?

If you don’t have a consistent rule, you’ll spend time deciding — or worse, filing it inconsistently. Filing rules eliminate that friction.

For each document type, you define a filing rule: a pattern describing where documents of that type should be stored. Whenever a document is assigned that type, Papermerge evaluates the rule and moves the document to the resulting path automatically.

The trailing / is significant:

  • A path ending with / — the last segment is a folder. The document is moved into that folder, keeping its original file name.
  • A path without a trailing / — the last segment is treated as the document name. The document is moved into the parent folder and renamed.

Examples:

Filing RuleMeaning
/home/Suppliers/AcmeGmbH/Target folder is AcmeGmbH. Document keeps its original name.
/home/Suppliers/AcmeGmbH/invoice.pdfTarget folder is AcmeGmbH. Document is renamed to invoice.pdf.
/home/Accounting/2024Target folder is Accounting. Document is renamed to 2024.

The root of every filing rule is always the user’s home folder. The /home/ prefix is implicit and can be omitted. The following paths are all equivalent:

  • /home/Invoices/Clients/
  • /Invoices/Clients/
  • Invoices/Clients/

The table below summarises how filing rules are evaluated:

Filing RuleDocument TitleResulting Path
/home/Suppliers/Invoices/acme-inv-042.pdf/home/Suppliers/Invoices/acme-inv-042.pdf
/home/Suppliers/Invoicesacme-inv-042.pdf/home/Suppliers/Invoices ⚠ document renamed
/Accounting/Correspondence/offer-letter.pdf/home/Accounting/Correspondence/offer-letter.pdf
Accounting/Correspondence/offer-letter.pdf/home/Accounting/Correspondence/offer-letter.pdf
/inbox/TaxDocuments/vat-return-2024.pdf/home/inbox/TaxDocuments/vat-return-2024.pdf

Static paths work well for simple cases, but sometimes the destination should depend on the document’s own data — for example, using a vendor name or invoice date from a custom field as part of the folder name. Filing rules support placeholders and conditions for this purpose.

A filing rule is evaluated each time a document type is assigned to a document. At that moment, Papermerge replaces any placeholders with the document’s actual values.

Placeholders are written between double curly braces: {{ ... }}. When Papermerge evaluates the rule, it replaces each placeholder with the corresponding value from the document.

The following placeholders are available:

PlaceholderReplaced with
{{ document.id }}The document’s unique ID. Always defined — safe to use as a fallback.
{{ document.title }}The document’s title.
{{ document.cf['Field Name'] }}The value of a custom field, referenced by its exact name.

Example:

/home/Invoices/Misc/{{ document.id }}-{{ document.title }}.pdf

This produces a path like /home/Invoices/Misc/42-acme-inv-042.pdf.

Sometimes you want the destination to depend on whether certain data is available. For example: file the document in a vendor-specific folder when the Vendor field is filled in, but fall back to a generic folder when it is not.

This is expressed using {% if %}...{% else %}...{% endif %} blocks:

{% if document.has_all_cf %}
/home/Invoices/{{ document.cf['Vendor'] }}/{{ document.cf['Invoice Date'] }}.pdf
{% else %}
/home/Invoices/Unsorted/{{ document.id }}.pdf
{% endif %}

Reading this rule top to bottom:

  • {% if document.has_all_cf %} — the condition: is every custom field filled in?
  • If yes: build the path from the Vendor and Invoice Date fields.
  • {% else %} — what to do if the condition is not met.
  • If no: place the document in Unsorted/ using the document ID.
  • {% endif %} — marks the end of the condition block.

document.has_all_cf is a built-in check that is true only when all custom fields have non-empty values. Using document.id as a fallback is a safe choice because it is always defined, regardless of whether metadata has been filled in.