npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@iamfj/n8n-nodes-paperless-ngx

v0.4.2

Published

n8n community node to automate Paperless-ngx document management: consume documents, correspondents, tags, document types and storage paths from your Paperless-ngx instance.

Readme

n8n-nodes-paperless-ngx

Automate your Paperless-ngx archive from n8n — and let AI agents search it.

npm CI License: MIT

  • Zero runtime dependencies, published with npm provenance from CI.
  • Works on API v9 and v10. The version is negotiated per request and falls back automatically, so the node doesn't break when you upgrade Paperless — or when you don't.
  • Uploads that actually finish. Paperless returns a task ID, not a document. This node waits for Consumption to complete and hands you the real document.
  • AI-agent ready. Every operation is exposed as a tool, so an agent can answer questions against your archive.
  • Push triggers, not polling. The trigger node provisions a Paperless-ngx workflow that calls n8n when a document is consumed, added or updated.

Operations

| Resource | Operations | |---|---| | Document | Get, Get Many (search, tag/Correspondent/date filters), Download (archived, original or thumbnail), Upload (waits for Consumption), Update, Delete | | Document Note | Get Many, Create, Delete | | Correspondent | Create, Get, Get Many, Update, Delete | | Tag | Create, Get, Get Many, Update, Delete | | Document Type | Create, Get, Get Many, Update, Delete | | Storage Path | Create, Get, Get Many, Update, Delete |

Correspondent, Document Type, Storage Path and Tag fields are dropdowns loaded from your instance; each also accepts an ID from an expression.

Triggers

The Paperless-Ngx Trigger node is a push trigger, not a poll. Activating it creates a Paperless-ngx Workflow with a Webhook action pointing at the node's own URL; deactivating it deletes that workflow again. Paperless does the matching, so n8n runs only when something you asked for actually happened.

| Event | Fires when | Carries a document ID | |---|---|---| | Document Added | a document finished Consumption | yes | | Document Updated | an existing document was edited | yes | | Consumption Started | a file entered Consumption | no — the document row does not exist yet |

Filters (Tags, Correspondent, Document Type, file name pattern) are stored on the Paperless trigger and evaluated there. Fetch Full Document loads the complete record over the API, because the webhook payload itself carries only the handful of fields Paperless renders into it. Verify Signature Header rejects calls that do not present the random value this node handed Paperless when it created the workflow.

Requirements:

  • Paperless-ngx 2.14 or newer — the Webhook action shipped in that release.
  • A token whose user may create workflows (/api/workflows/). A token that can read documents but not write workflows fails at activation with a 403 rather than silently never firing.
  • An n8n instance Paperless can reach. The webhook URL is the one n8n shows on the node; if that is a localhost address, Paperless in another container will not resolve it.

Installation

Self-hosted, through the UI

Settings → Community Nodes → Install, then enter:

@iamfj/n8n-nodes-paperless-ngx

Two environment variables matter here:

  • N8N_COMMUNITY_PACKAGES_ENABLED must be true. It is the default, so this only bites on instances that turned it off deliberately.
  • N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true is required to use this node as an AI-agent tool. Without it the node installs and works in ordinary workflows but never appears in an AI Agent's tool list — which looks like a broken node rather than a missing setting.

Self-hosted, manually

docker exec -it n8n sh        # if you run n8n in Docker
mkdir -p ~/.n8n/nodes && cd ~/.n8n/nodes
npm i @iamfj/n8n-nodes-paperless-ngx

Then restart n8n. If ~/.n8n is a volume but its node_modules is not — which is the usual result of a docker compose file that mounts only the data directory — set N8N_REINSTALL_MISSING_PACKAGES=true so the package is reinstalled when the container is recreated.

n8n Cloud

Search for Paperless-ngx in the nodes panel and install it.

Self-hosted gotchas

These account for most of the "it doesn't work" reports:

  • http://localhost:8000 does not resolve from inside the n8n container. localhost is the n8n container itself, not your Paperless one. Use the Docker Compose service name (http://paperless-webserver:8000), a LAN address, or your public hostname.
  • The Base URL is the instance root, with no /api suffix. https://paperless.example.com, not https://paperless.example.com/api — the node appends /api itself.
  • Self-signed certificates need the credential's Ignore SSL Issues (Insecure) toggle. The raw Node.js error otherwise reads as a connection failure rather than a certificate one.
  • The token scheme is Token, not Bearer. The node sends the right one; this matters if you are comparing against a curl command that works.

Troubleshooting

The node's error messages carry these hints already; the table is here so the two agree.

| Symptom | Cause | Fix | |---|---|---| | 401, "Invalid token" | Token copied from the wrong place, or an OAuth-style Bearer scheme expected | Re-copy from My Profile → API Token in Paperless-ngx | | 403 on one object, 200 on others | Object-level permission in Paperless-ngx | Grant the token's user access to that object — the credential is fine | | 404 on every request | Base URL points somewhere other than the instance root — a trailing /api is the one suffix the node drops for you, a subpath is not | Use the instance root | | 406 | The pinned API version is not served by this instance | Set API Version to Auto in the credential | | 413 on upload | The reverse proxy body limit, not a Paperless setting | Raise nginx client_max_body_size | | "replied with an HTML page instead of JSON" | Base URL points at the web UI or at a proxy error page | Check the URL and the proxy in front of it | | Node missing from an AI Agent's tool list | N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE is unset | Set it to true and restart n8n | | Upload times out | OCR on a long scan genuinely takes minutes | Raise Timeout (Seconds) on the Upload operation | | 403 when activating the trigger | The token's user may not create Paperless workflows | Use a token whose user has workflow permissions | | Trigger activates but never fires | Paperless refuses the webhook URL: PAPERLESS_WEBHOOKS_ALLOWED_SCHEMES (default http,https), PAPERLESS_WEBHOOKS_ALLOWED_PORTS (default: all) or PAPERLESS_WEBHOOKS_ALLOW_INTERNAL_REQUESTS (default true) | Allow the scheme, port and — for a webhook URL on a private address — internal requests | | Trigger fires, but the payload's url is empty | PAPERLESS_URL is unset, so Paperless has no absolute URL to render | Set PAPERLESS_URL on the Paperless instance | | 400 "workflow with this name already exists" | A previous Paperless workflow from this node was deleted from n8n's side only | Delete the leftover n8n … workflow in Paperless → Workflows |

Credentials

  1. In Paperless-ngx, open My Profile and copy your API Token.
  2. In n8n, create a Paperless-Ngx API credential:

| Field | Value | |---|---| | Base URL | https://paperless.example.com — no /api suffix | | API Token | the token from step 1 | | API Version | Auto unless you depend on a specific response shape | | Ignore SSL Issues | only for self-signed certificates |

Hit Test — it confirms the URL and the token against /api/profile/.

Usage

File every email attachment into Paperless-ngx

Copy this into an n8n canvas (Ctrl/Cmd+V pastes workflow JSON directly). It watches a mailbox, sends each attachment to Consumption, and — because Wait for Consumption is on — returns the finished document rather than a task ID, so the next node can act on the real document.

{
  "name": "Email attachments → Paperless-ngx",
  "nodes": [
    {
      "parameters": {
        "format": "resolved",
        "options": {}
      },
      "type": "n8n-nodes-base.emailReadImap",
      "typeVersion": 2,
      "position": [0, 0],
      "id": "8f7a1c2e-0000-4000-8000-000000000001",
      "name": "Email Trigger (IMAP)"
    },
    {
      "parameters": {
        "resource": "document",
        "operation": "upload",
        "binaryPropertyName": "attachment_0",
        "waitForConsumption": true,
        "timeout": 300,
        "additionalFields": {
          "title": "={{ $json.subject }}"
        }
      },
      "type": "@iamfj/n8n-nodes-paperless-ngx.paperlessNgx",
      "typeVersion": 1,
      "position": [220, 0],
      "id": "8f7a1c2e-0000-4000-8000-000000000002",
      "name": "Paperless-ngx"
    }
  ],
  "connections": {
    "Email Trigger (IMAP)": {
      "main": [[{ "node": "Paperless-ngx", "type": "main", "index": 0 }]]
    }
  }
}

attachment_0 is the first attachment; the IMAP node numbers them from zero. Raise Timeout (Seconds) if OCR on your scans takes longer than five minutes.

Act on every document Paperless-ngx files

This one runs the other way round: Paperless calls n8n. Activate the workflow and the trigger provisions the Paperless-ngx side by itself.

{
  "name": "New invoice → notify",
  "nodes": [
    {
      "parameters": {
        "event": "documentAdded",
        "filters": {
          "tags": [3]
        },
        "fetchFullDocument": true
      },
      "type": "@iamfj/n8n-nodes-paperless-ngx.paperlessNgxTrigger",
      "typeVersion": 1,
      "position": [0, 0],
      "id": "8f7a1c2e-0000-4000-8000-000000000003",
      "name": "Paperless-ngx Trigger"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "8f7a1c2e-0000-4000-8000-000000000005",
              "name": "message",
              "type": "string",
              "value": "={{ $json.title }} was filed as document {{ $json.docId }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [220, 0],
      "id": "8f7a1c2e-0000-4000-8000-000000000004",
      "name": "Build Message"
    }
  ],
  "connections": {
    "Paperless-ngx Trigger": {
      "main": [[{ "node": "Build Message", "type": "main", "index": 0 }]]
    }
  }
}

Tag ID 3 is a placeholder — pick your own from the node's Tags dropdown. With Fetch Full Document on, the complete document record arrives under document, next to the docId, title and url Paperless renders into the webhook itself.

Let an AI agent search the archive

Connect a Paperless-ngx node to an AI Agent's Tool input and set it to Document → Get Many with the Filters → Text filter driven by the model. The agent then answers questions like "what did the electrician invoice in March?" by searching your archive instead of guessing.

Self-hosted instances need N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true for the node to appear in the tool list at all — see Installation.

Compatibility

Paperless-ngx serving API v9 or v10, and Node.js 20 or 22. Both API versions are exercised by the test suite; the node negotiates between them per request. The trigger node additionally needs Paperless-ngx 2.14 or newer, which is where the Webhook workflow action shipped.

Resources

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md for setup and the house style, and docs/architecture/shared-kernel.md for why the code is shaped the way it is.

License

MIT © Fabian Jocks

This project is not affiliated with or endorsed by the Paperless-ngx project or n8n GmbH.