postulo-paperless: keep every document in Paperless-ngx #15

Closed
opened 2026-09-05 12:29:12 +00:00 by tiagoagueda · 0 comments
Owner

Observation

postulo-paperless - ability to use paperless to store all kinds of documents

Why Paperless-ngx

It is the self-hoster's document archive (GPL-3.0, Django as well), and it has the API this needs: token authentication; consumption through POST /api/documents/post_document/ as multipart with document, title, created, correspondent, document_type, tags and custom_fields; a task id back, polled at /api/tasks/, that resolves to the document once consumed; and documents can be found again by tag, correspondent or custom field. Paperless also refuses a document whose checksum it already holds, which makes re-sending idempotent for free.

Shape

  • A separate package and repository, postulo-paperless, registering a store in the postulo.stores group (#13) and using a connection (#11): Paperless URL and API token (secret). Test lists one document with the token.
  • Mapping, all created on the Paperless side when missing:
    • correspondent ← company
    • document type ← "CV", "Cover letter", or the upload's DocumentKind
    • tags ← postulo, plus one tag per application (or a custom field — see the open questions)
    • custom field Postulo ← the application's URL on the instance, so a document found in Paperless leads back to its application
    • title ← "CV — Company — Role — date", and created ← the date it was sent
  • Asynchronous end to end: post, keep the task id, poll until consumed, store the resulting document id and URL as the ExternalRef. A "duplicate" answer counts as success, with the existing document's id.
  • Archive semantics. Withdrawing or declining an application deletes nothing in Paperless; an archive is for keeping.
  • Stage two, read-back: browse() against the Paperless API to attach a document that already lives there — a signed contract, a letter that came by post — to an application.
  • Network. Paperless almost always sits on the same LAN or Compose network, so this plugin is the reason #11's outbound policy has an operator switch for private destinations.
  • Compose. The image question from #5 — how an operator adds a plugin package to the container — applies here identically, and Paperless users are container users.

Classification

Enhancement. A separate package; changes nothing unless installed and connected. Not breaking.

Depends on

  • #11 — connection and secret storage, outbound policy
  • #13 — the store interface it implements

Open questions

  1. One tag per application, or a custom field only? Tags multiply fast; a custom field is cleaner and searchable.
  2. Send the job posting text itself as a document too, so the archive holds what one applied to as well as with? Cheap, and useful once the posting disappears from the web.
  3. Storage paths: let the person pick a Paperless storage path for Postulo's documents, or leave Paperless's default?
## Observation > postulo-paperless - ability to use paperless to store all kinds of documents ## Why Paperless-ngx It is the self-hoster's document archive (GPL-3.0, Django as well), and it has the API this needs: token authentication; consumption through `POST /api/documents/post_document/` as multipart with `document`, `title`, `created`, `correspondent`, `document_type`, `tags` and `custom_fields`; a task id back, polled at `/api/tasks/`, that resolves to the document once consumed; and documents can be found again by tag, correspondent or custom field. Paperless also refuses a document whose checksum it already holds, which makes re-sending idempotent for free. ## Shape - **A separate package and repository, `postulo-paperless`**, registering a **store** in the `postulo.stores` group (#13) and using a **connection** (#11): Paperless URL and API token (secret). *Test* lists one document with the token. - **Mapping**, all created on the Paperless side when missing: - correspondent ← company - document type ← "CV", "Cover letter", or the upload's `DocumentKind` - tags ← `postulo`, plus one tag per application (or a custom field — see the open questions) - custom field `Postulo` ← the application's URL on the instance, so a document found in Paperless leads back to its application - title ← "CV — Company — Role — date", and `created` ← the date it was sent - **Asynchronous** end to end: post, keep the task id, poll until consumed, store the resulting document id and URL as the `ExternalRef`. A "duplicate" answer counts as success, with the existing document's id. - **Archive semantics.** Withdrawing or declining an application deletes nothing in Paperless; an archive is for keeping. - **Stage two, read-back**: `browse()` against the Paperless API to attach a document that already lives there — a signed contract, a letter that came by post — to an application. - **Network.** Paperless almost always sits on the same LAN or Compose network, so this plugin is the reason #11's outbound policy has an operator switch for private destinations. - **Compose.** The image question from #5 — how an operator adds a plugin package to the container — applies here identically, and Paperless users are container users. ## Classification Enhancement. A separate package; changes nothing unless installed and connected. Not breaking. ## Depends on - #11 — connection and secret storage, outbound policy - #13 — the store interface it implements ## Open questions 1. One tag per application, or a custom field only? Tags multiply fast; a custom field is cleaner and searchable. 2. Send the job posting text itself as a document too, so the archive holds what one applied *to* as well as *with*? Cheap, and useful once the posting disappears from the web. 3. Storage paths: let the person pick a Paperless storage path for Postulo's documents, or leave Paperless's default?
tiagoagueda added this to the 0.2.0 milestone 2026-09-05 12:29:12 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
Postulo/postulo#15
No description provided.