
Paperless-ngx Connector
Turn Paperless-ngx documents into draft vendor bills with the PDF attached - never auto-posted, guarded vendor, idempotent, read-only upstream.
Available for Odoo 16.0, Odoo 17.0, Odoo 18.0, Odoo 19.0. Technical name bambooforge_paperless_connector.
Paperless-ngx Connector
A read-only importer that catalogs your Paperless-ngx document archive inside Odoo 18: it pulls your correspondents, document types, tags and documents — with their OCR text — into searchable Odoo records, over the Paperless REST API, with a resilient job queue, dry-run safety and pre-flight validation so you stay in control.
This page is the complete manual. If you follow it top to bottom you can install, connect, run your first import, automate it, and fix the common issues without contacting support.
Overview
The connector reads four source entities from Paperless-ngx over its REST API and keeps a local, searchable mirror of them in Odoo. Direction of data is one way: Odoo ← Paperless-ngx (read-only). The connector never writes anything back to Paperless.
Correspondents — the senders / recipients registered in Paperless: name and the document count Paperless reports. Imported into Paperless Connector ▸ Catalog ▸ Correspondents.
Document Types — the classification types documents are filed under: name and document count. Imported into Catalog ▸ Document Types.
Tags — the tags used across the archive: name, colour (the Paperless API exposes colour and/or color) and document count. Imported into Catalog ▸ Tags.
Documents — every document with its title, OCR content (the extracted text Paperless stores), creation date, archive serial number (ASN), and its links to a correspondent, a document type and any number of tags. Imported into Catalog ▸ Documents.
Correspondents, document types and tags are imported before documents, so each document resolves its correspondent (many-to-one), document type (many-to-one) and tags (many-to-many) from the records already imported.
Every remote call goes through a queue: nothing is written to Odoo until a job runs, jobs retry with back-off on transient failures, and a circuit breaker pauses an instance that keeps failing.
Requirements
Odoo: 18.0, Community or Enterprise. The module depends only on base and mail, which are always present.
Paperless-ngx: any Paperless-ngx server that exposes the standard REST API (/api/correspondents/, /api/document_types/, /api/tags/, /api/documents/) with Django REST Framework pagination. It must be reachable from the Odoo server.
Python: no extra libraries beyond a standard Odoo 18 install.
Odoo access: any internal user can use the connector screens. The Paperless API token is stored in a system-only field, so only the Settings / Administration user can read or change it.
Network: outbound HTTP/HTTPS from Odoo to your Paperless server. By default the connector refuses internal/loopback/private hosts as an SSRF safeguard (see Safety features).
Installation
Copy bambooforge_paperless_connector into your Odoo addons path.
Restart the Odoo service.
Open Apps, click Update Apps List, search for Paperless, and press Activate / Install. Dependencies (base, mail) install automatically.
No Paperless-ngx server is required to evaluate the connector: a mock Paperless REST API ships inside the module, so you can install, explore and run the full import flow against sample data before pointing it at a real server. To use it, set the instance Base URL to your own Odoo address, set API Path to paperless/mock_api, enter any token, and turn Allow internal host on (because the mock lives on your own server). See Step 2 and the FAQ.
Step 1 — Create an API token in Paperless-ngx
Paperless-ngx authenticates every request with a single API token sent as the Authorization: Token <token> HTTP header. To create one:
Sign in to your Paperless-ngx web interface as the user whose access you want the connector to use.
Open Settings ▸ My Profile (the user-profile / account page).
Find the API Token (Auth Token) field. If no token is shown yet, use the control to generate / regenerate one.
Copy the token string. You will paste it into Odoo in the next step.
The connector only ever issues GET requests, so a token for a read-capable user is enough. The token is the only credential the connector needs.
Step 2 — Create the connection in Odoo
Open Paperless Connector ▸ Configuration ▸ Instances and create a record.
Key fields:
Field |
What to enter |
|---|---|
Name |
A label for this server, e.g. Office Paperless. |
Base URL |
Your Paperless root, e.g. https://paperless.example.com (or http://localhost:8000 for a local server, which also needs Allow internal host). |
Authentication |
API Token — the only mode Paperless uses. |
API Token |
The token from Step 1. Sent as the Authorization: Token <token> header on every request. Visible to administrators only. |
API Path |
Leave the default api (the client builds <base_url>/api/documents/, etc.). Set it to paperless/mock_api only to drive the bundled mock. |
Verify SSL |
Keep on for production. Turn off only for self-signed test certificates. |
Allow internal host |
Off by default. Turn on only to reach a Paperless server on localhost or a private network — or to drive the bundled mock (lowers the SSRF guard; see Safety features). |
Then click Test Connection. The connector lists one document to confirm the token and URL; a green Connected state means both are correct. If it fails, the exact error is recorded on the form (Last Connection Error) and in Logs (see Troubleshooting).
Tip: use Quick Setup (button on the instance) to install starter import flows and apply a recommended safety profile in one step.
Step 3 — First import (dry-run, then live)
New instances start with Dry-run ON. In dry-run, import jobs simulate writes: instead of creating records they produce Validation Results you can review under Paperless Connector ▸ Operations ▸ Validation Results. This lets you confirm what would happen before anything is written.
To run a first import:
On the instance, click Import Documents. Because documents reference correspondents, document types and tags, this enqueues the master-data imports first and the documents last, so every link can resolve. (You can also import Correspondents, Document Types or Tags on their own.) Enqueuing does not block the UI.
Jobs are processed by the Paperless Queue Processor scheduled action (every minute), or immediately if you run it manually from Operations ▸ Queue Jobs.
Review Validation Results while still in dry-run.
When satisfied, open the instance, turn Dry-run OFF, and run the imports again to write the records for real.
Imported records land under Paperless Connector ▸ Catalog: Correspondents, Document Types, Tags and Documents. Each carries its Paperless id, so re-imports update the same record instead of duplicating it.
Field mapping & customization
Field Mappings (Configuration) map Paperless source fields to Odoo fields per entity (correspondent / document_type / tag / document). The core fields (title → name, OCR content, created date, ASN, the correspondent / document-type / tag links) are mapped out of the box; use Generate suggested mappings on the instance to seed extra ones, then adjust.
Schema Fields lists the discovered Paperless fields per entity alongside the matching Odoo fields. Run Schema Introspection on the instance to refresh it by sampling a live record (it falls back to the bundled mock shape if the API is unreachable).
Per-entity import limits on the instance cap how much each run pulls: Correspondents / Document Types / Tags default to 100, Documents to 200. Raise them for large archives.
There is no order-status, stock, image, tax or export configuration: this is a read-only importer. (A dormant State Mappings menu exists for framework compatibility and is hidden from normal users.)
Automation (scheduled actions)
The module ships these scheduled actions (Settings ▸ Technical ▸ Scheduled Actions):
Scheduled action |
Default |
Purpose |
|---|---|---|
Paperless Queue Processor |
every 1 min |
Processes queued import jobs. |
Paperless Reconciliation |
every 15 min |
Re-lists each enabled entity and queues imports for records missing locally or whose previous job failed. |
Paperless Maintenance |
every 1 hr |
Recovers stale/locked jobs and trims old jobs and logs. |
Paperless Flow Scheduler |
every 5 min |
Runs scheduled import flows. |
Paperless Flow Metrics |
every 1 hr |
Aggregates flow-run metrics. |
Paperless Auto Recover |
every 15 min |
Reopens a tripped circuit breaker once the server is healthy again. |
Turn on Auto import and/or Auto reconcile per entity on the instance (correspondents, document types, tags, documents) to let the scheduled actions keep the catalog current hands-free. They are off by default.
The connector follows the Django REST Framework pagination cursor: each list page carries a next URL, and the client walks it to accumulate every page, so large libraries import fully across pages (subject to the per-entity import limits).
Webhooks are not used. Paperless-ngx is imported by polling on a schedule. A /paperless/webhook route exists but is intentionally neutralized — it always answers not supported (HTTP 501). Real-time push is a roadmap item, not part of this read-only version; scheduled reconciliation keeps data current.
Safety features
Dry-run mode — simulate writes and review Validation Results before going live (field Dry-run, ON by default).
Pre-flight validation — jobs are validated before they run; Minimal / Standard / Strict business validation profiles gate risky writes (field Business validation profile, default Standard).
Resilient queue — every import is a job with a retry limit and exponential back-off; exhausted jobs move to a dead-letter state instead of looping.
API-level retries — transient HTTP failures (timeouts, 429 rate limits, 5xx) are retried with their own capped exponential back-off before a job is marked failed.
Circuit breaker — after repeated failures an instance auto-pauses (Tripped); the Auto Recover action reopens it once Paperless responds again. An auth/configuration failure trips it immediately.
Rollback snapshots — when Rollback is enabled, imports capture a snapshot so you can undo a batch from Operations ▸ Rollback Snapshots.
SSRF guard — the connector refuses internal/loopback/private hosts (including cloud metadata addresses) unless Allow internal host is explicitly enabled.
Troubleshooting
Symptom |
Cause and fix |
|---|---|
Test Connection fails with 401/403 |
Wrong or expired API token, or the token's user cannot read the API. Re-check Step 1, regenerate the token in Settings ▸ My Profile, and paste it again. The connector sends Authorization: Token <token>. |
"is not allowed because it resolves to a non-public address" |
Base URL points at localhost/a private IP (or a cloud metadata address). Enable Allow internal host on the instance for a self-hosted / local Paperless, or use a public URL. |
SSL errors on Test Connection |
Self-signed or untrusted certificate. Install a valid certificate, or turn off Verify SSL for testing only. |
Test Connection times out / network error |
Paperless is unreachable from the Odoo server, or the URL is wrong. Confirm the Base URL opens in a browser from the server's network; raise Timeout (seconds) if the server is just slow. |
Only part of a large library imported |
Each run is capped by the per-entity import limit (Documents default 200). Raise the Documents / Correspondents / Document Types / Tags import limit on the instance, or let Reconciliation catch up over its 15-minute runs; the client already follows DRF pagination next to read every page. |
A document has no correspondent / type / tags |
Those parents had not been imported yet when the document ran. Re-run Import Documents (it imports the parents first) or run the parent imports, then re-import documents; links resolve best-effort from imported records. |
Jobs stay in Pending |
The Queue Processor is off, or the instance is paused. Check the Paperless Queue Processor scheduled action is active and the instance is not Paused. |
Instance shows Tripped |
Circuit breaker tripped after repeated failures (auth/config trips it at once). Fix the token/URL; Auto Recover reopens it after a cooldown, or click Resume. |
Records imported twice |
Imports are keyed by the Paperless id, so this should not happen. If it does, check that two instances do not point at the same Paperless server. |
Nothing happens after Import |
You are in Dry-run. Review Validation Results, then turn dry-run off and re-run. |
Rate-limit (429) errors in Logs |
Paperless throttled the burst. The client already retries 429s with back-off; lower the per-entity import limits or raise API retry settings if it persists. |
For anything else, Operations ▸ Logs records every API call, level and error with a timestamp.
Frequently asked questions
Which versions are supported? Odoo 18.0 on the Odoo side. On the Paperless side the connector targets the standard Paperless-ngx REST API with DRF pagination; validate your exact build with the bundled mock first.
Do I need Paperless-ngx installed to evaluate it? No. A mock Paperless REST API ships inside the module. Set the instance Base URL to your Odoo address, API Path to paperless/mock_api, enter any token, and enable Allow internal host — then run the full import flow against sample data.
How does authentication work? Create an API token in Paperless under Settings ▸ My Profile. The connector sends it as the Authorization: Token <token> header on every request. There is no username/password, OAuth or consumer-key flow.
Does it write anything back to Paperless? No. The connector is read-only by design: it only issues GET requests and never creates, edits or deletes anything in Paperless. It is a safe, auditable mirror.
Does it download the document files (PDFs, images)? No. It imports the document metadata and OCR text — title, OCR content, creation date, archive serial number, and the correspondent / document-type / tag links. The original file binaries are not downloaded or stored in Odoo.
How does it keep up to date? By polling on a schedule. The Reconciliation action re-lists each enabled entity and queues imports for anything new or previously failed. There is no webhook ingestion (the /paperless/webhook route returns not supported).
Is it safe to run against real data? Dry-run is ON by default, validation gates risky writes, and rollback snapshots let you undo. You decide when to go live. And because it only reads from Paperless, the remote archive is never at risk.
What support and refund policy do I get? Every request is answered within 24 hours, setup help included. If you report a bug within 2 months of purchase and it is not resolved within 15 days, you are entitled to a full money-back refund.
Data, privacy & limits
The connector reads correspondents, document types, tags and documents (including their OCR text content) from your Paperless-ngx server and writes the corresponding Odoo catalog records. It never writes back to Paperless.
Document file binaries are not downloaded — only the title, OCR text, dates, archive serial number and the correspondent/type/tag links are imported. To open the original file, use Paperless itself.
The API token is stored in a system-only (administrator-only) field.
In scope today: read-only import of the four entities, OCR text, scheduled reconciliation, dry-run, validation, rollback snapshots, schema introspection, field mappings and the multi-step flow engine.
Out of scope / roadmap: any write-back to Paperless; downloading file binaries; webhook / real-time push (the route exists but is neutralized); incremental list filtering by timestamp (v1 lists by pagination cursor).
Support & updates
Support: support@bambooforge.dev — answered within 24 hours, setup help included.
Refund: report a bug within 2 months of purchase; if unresolved within 15 days, full refund.
Full source is included. Updates track the supported Odoo 18 / Paperless-ngx REST API line.
Upgrading & version compatibility
This build targets Odoo 18.0. Each Odoo major series (17.0, 18.0, 19.0) has its own dedicated build of this module — always install the build that matches your Odoo version. Mixing a build with a different Odoo series is not supported.
Patch upgrades (same series, e.g. 18.0.1.0.0 → later)
Back up your database and filestore first.
Replace the module folder with the newer build.
Restart Odoo with the module updated:
./odoo-bin -c your.conf -u bambooforge_paperless_connector -d your_db
Odoo applies any schema/data changes automatically. Your existing records and configuration are preserved.
Cross-version migration (e.g. Odoo 17 → 18)
Upgrading Odoo itself is a database migration handled by Odoo's standard upgrade tooling. When you migrate the database to the next Odoo series, install the matching build of this module for that series. Data created by this module carries over with the database migration.
After any upgrade the module's scheduled actions resume on their normal cadence — no manual re-activation is required.
Uninstallation
You can remove this module at any time from Apps → (this module) → Uninstall, or from the command line. Uninstalling is clean and reversible by reinstalling — but note what is and is not deleted.
What is removed
The module's own tables and every record in them (24 models, prefixed paperless.*) — this is the data this module created.
The menus, actions, views and reports this module installed.
Its scheduled actions (cron jobs) — they stop immediately on uninstall.
Connection records, credentials, field mappings, queue jobs and sync logs stored in Odoo.
What is preserved
Your remote platform is never touched. Uninstalling only removes the Odoo-side connector; products, customers and orders on the external store/service are untouched.
Records already imported into standard Odoo models (e.g. contacts, products, sales orders) remain — they are ordinary Odoo records once created.
Attachments and chatter messages on standard records are kept.
As always, take a database backup before uninstalling in production.
Changelog
18.0.1.0.0
Current release for Odoo 18.0. This build includes:
Turn Paperless-ngx documents into DRAFT Odoo 18 vendor bills (account.move) with the PDF attached.
Never auto-posted, guarded vendor, idempotent.
Plus a searchable catalog of documents, correspondents, types & tags. Read-only against Paperless, resilient queue, dry-run.
Feature additions and fixes ship as new builds on the Odoo Apps store; this page and the module's version reflect the current published release. Always keep the build matched to your Odoo series (see Upgrading & version compatibility).
Screens


